Review R8 m7: after the merge with main's 732b63d61a the probe decodes launcher
stdout as UTF-8 through ProcessStartInfo.StandardOutputEncoding and never touches
[Console]::OutputEncoding, so the test docstrings no longer claim the call sites
scope and restore it. runtime.ps1 keeps a one-line #124526 pointer at the
encoding line. Behaviour and assertions are unchanged.
Invoke-HermesProbe handed a .cmd launcher to Process.Start with
UseShellExecute=false, letting CreateProcess pick the interpreter and
re-parse the arguments. Run it through ComSpec explicitly like the update
step does, and refuse arguments cmd.exe cannot be made to take literally.
(cherry picked from commit 0b24aab96962535268d71711c0ef564e01ac6e11)
- marker helpers move to scripts/desktop-update/marker.ps1, dot-sourced
first (windows.ps1 2113 -> 1930 lines); a hand-off that cannot load it
exits 3 having changed nothing. It ships in the checkout next to
windows.ps1 and runtime.ps1, which is where the Desktop runs them from.
- creation time comes from Win32_Process.CreationDate (limited query
rights), cached per pid while it lives: Get-Process .StartTime is access
denied for SYSTEM/elevated/other-user pids under PowerShell 5.1, so a
pid reused by a service after a reboot read as a live owner forever.
Alive with an unreadable time is live only inside the 20-minute ceiling.
- -DesktopPid runs adopt the Desktop's live bridge claim only; a refused
run exits 2 without a result file and only reopens a Desktop that is gone.
- positional parse identical to the other readers; claims publish the
complete body with an exclusive hard link (rename fallback); a fresh
empty marker is a claim in flight; the delegate line always carries ct.
- a follow-up step whose process tree cannot be quiesced after the commit
point is ok:true + a manual warning (no relaunch, marker kept live),
not "still on the previous version".
- the interrupted post-update tail is always a manual warning: re-running
hermes update is the only remedy, so the copy says exactly that.
- the launcher probe bound is a -ProbeTimeoutSeconds parameter (default
60), not the HERMES_UPDATE_PROBE_TIMEOUT_SECONDS environment variable.
(cherry picked from commit 65663dc6a64f942c6385b7de3ba13cdecd393387)
windows.ps1 implements update-marker contract C1 v2 and the C3 outcome
vocabulary on the Windows Desktop hand-off:
- The marker claim is the script's first action (before any Add-Type, UI
or probe): exclusive create (tmp + File.Move, never overwrites) with a
v2 body "<pid>\n<started_at>\nct:<creation time>\n". A live marker owned
by exactly -DesktopPid is adopted by compare-and-swap keeping its
started_at; any other live owner refuses the run (exit 2, marker
untouched, "Nothing was changed"); a dead owner (pid gone, creation time
mismatch = pid reuse, v1 older than 20 min) is compare-and-deleted and
the claim retried.
- Release is compare-and-delete on lines 1-3 and keeps the marker while a
line-4 delegate is alive. When a stalled tree cannot be quiesced (exit 7)
the marker gains a delegate line naming a surviving job member
(JobObjectBasicProcessIdList), so it stays live exactly as long as the
tree does instead of naming the dying script.
- After `hermes update` exits 0 (or the 124 banner remap) the result is
ok:true, exit_code 0: verify failure (was exit 8), legacy rebuild
failure (was exit 6), a gateway restart miss, an interrupted post-banner
phase and any unexpected throw become `warnings` + manual, with a
"Hermes was updated, but ..." message; gateway start --all still runs
after a failed verify/rebuild.
- The idle watchdog counts job CPU/IO accounting deltas as progress, so a
pipe-silent but busy step (download, extraction) is not killed.
- Launcher probes (--print-runtime-command, --version, update --help) run
with a 60 s timeout and kill their tree on expiry.
- Desktop exit wait checks pid + creation time pinned at start, and a
still-open Desktop is never relaunched over (exit 4).
- The result file is written atomically, carries started_at (marker line
2) and warnings, and is no longer deleted at hand-off start.
- Stop-UiServer only removes its own profile dir and dirs whose pid is not
running (TEMP is shared across HERMES_HOMEs).
(cherry picked from commit af178fd695d7f94bf584bfabe9748cbb752fea13)
Extends #124526's class fix to the two remaining native captures that can
carry a profile path, and closes the secondary issue from the report:
- scripts/desktop-update/runtime.ps1: the launcher --print-runtime-command
JSON and the legacy user-bin --version 'Install directory:' capture are
both scoped to [Console]::OutputEncoding = UTF-8 and restored in finally,
matching install.ps1's Invoke-Native -Utf8Output and every other consumer
of the boundary (windows_ssh_runtime, the Electron updater, the Rust
bootstrap all decode UTF-8). PS 5.1's OEM decode mojibaked the reported
install root so the legacy identity check never matched on a non-ASCII
profile.
- scripts/install.ps1: -HermesHome equal to or inside -InstallDir puts the
pm tool store inside the checkout; the repository stage's occupied-
directory preflight then refuses every retry after the first run
populated <InstallDir>\tools. Refused up front unless HERMES_RUNTIME_DIR
parks the store elsewhere.
Tests: tests/scripts/desktop_update/test_desktop_update_runtime_unicode.py
(real published launcher, non-ASCII profile, CP936/437/65001, encoding
restore) and scripts/tests/test-install-ps1-store-guard.ps1 (real installer
subprocess through -ShowResolvedPaths: refusal, escape hatch, defaults).
Co-authored-by: 择梦舟 <158067205+dreamfarer-space@users.noreply.github.com>
Reconcile plugin declarations and validation through PM's atomic generation publication; preserve external runtimes, target markers, and conflict refusal. Keep one source-update completion owner and port upstream lifecycle changes to the PM desktop/runtime paths.
Competing installers and checkout-local venv assumptions bypassed PM
selection, install consent, and generation lifetimes. Route consumers
through PM and installation-bound launchers. Refresh source launchers
before obsolete Python entries can be collected.
Remove Node, browser, and CUA acquisition engines, obsolete venv-holder
handling, detached sync, and unused PM APIs. Keep historical updater
exports inert and preserve external tool ownership and native integration.
Share product freshness and prepared inputs across builders. Align plugin
admission, Docker provisioning, setup instructions, and behavioral tests.
Verified targeted Python and JavaScript tests, desktop and web typechecks,
scoped lint, real product builds, and the Docker frontend smoke test.
The missed post-setup test cleanup is included and verified.
Native Windows/macOS execution, full Rust compilation, and the complete
repository suite remain unverified. Historical compatibility requirements
were preserved and extended, not fully rescanned.