From f10a231efae89d9abfc7770e931d74c75978b832 Mon Sep 17 00:00:00 2001 From: fangliquanflq Date: Sat, 15 Aug 2026 20:59:54 +0800 Subject: [PATCH] fix(scripts): clarify Windows update retry marker semantics --- scripts/desktop-update/retry-policy.ps1 | 6 ++++-- scripts/desktop-update/windows.ps1 | 7 +++++-- tests/test_desktop_update_windows_retry_policy.py | 2 +- 3 files changed, 10 insertions(+), 5 deletions(-) diff --git a/scripts/desktop-update/retry-policy.ps1 b/scripts/desktop-update/retry-policy.ps1 index a36187b684..771c5dd1a8 100644 --- a/scripts/desktop-update/retry-policy.ps1 +++ b/scripts/desktop-update/retry-policy.ps1 @@ -8,8 +8,10 @@ function Test-HermesUpdateShouldRetry { if ($ExitCode -ne 2) { return $true } # Exit 2 is shared by non-retryable safety refusals and the self-lock - # deferral. Only the latter writes this marker, which a fresh Python - # process consumes before importing native modules. + # deferral. Only the latter writes this marker. The handoff treats it as a + # retry signal for one fresh-process attempt; early recovery does not run + # while argv contains "update". $deferredInstallMarker = Join-Path $InstallRoot ".update-incomplete" return Test-Path -LiteralPath $deferredInstallMarker } + diff --git a/scripts/desktop-update/windows.ps1 b/scripts/desktop-update/windows.ps1 index 67e6f8ab81..4249b2f489 100644 --- a/scripts/desktop-update/windows.ps1 +++ b/scripts/desktop-update/windows.ps1 @@ -1502,8 +1502,11 @@ try { if (Test-HermesUpdateShouldRetry -ExitCode $res.Code -InstallRoot $InstallRoot) { # One retry for update-boundary failures. Most exit-2 safety refusals # remain terminal, but self-lock deferral also uses exit 2 and writes - # .update-incomplete after the code swap. A fresh process consumes that - # marker before native imports, then resumes the full update pipeline. + # .update-incomplete after the code swap. That marker is only a retry + # signal here: early recovery skips argv containing "update", so this + # fresh process must finish dependency sync without holding the locked + # native modules (lazy imports on the swapped checkout), then continue + # the remaining Desktop/skills stages of the full update pipeline. Write-HandoffLog "first attempt left retryable update state; retrying once in a fresh process" Publish-UiProgress "Retrying update" $res = Invoke-HermesStep $pythonExe $updateArgs "update" diff --git a/tests/test_desktop_update_windows_retry_policy.py b/tests/test_desktop_update_windows_retry_policy.py index 25e07f3c40..8fafbca24c 100644 --- a/tests/test_desktop_update_windows_retry_policy.py +++ b/tests/test_desktop_update_windows_retry_policy.py @@ -53,4 +53,4 @@ def test_retry_policy_distinguishes_self_lock_deferral(tmp_path: Path) -> None: "withoutMarker": [False, True, False], "withMarker": True, } - assert marker.exists() \ No newline at end of file + assert marker.exists()