fix(desktop): report a failed gateway restart as a manual step, not a failed update

The salvaged restart (#119815) exited 9 when `hermes gateway start --all`
failed, which makes the hand-off's finally block write ok:false, show the
error finale and log "detached update FAILED" in the Desktop even though
the code, venv and Desktop build all verified. Move the restart after the
outcome is settled and surface a restart failure through Write-Result's
existing manual flag instead: the Desktop's boot dialog shows the
`hermes gateway start --all` follow-up, and the update stays a success.
Publish a UI stage so the marquee names the step.

Extend the salvaged test with the exit-code invariant (red on the PR's
own head) and correct the update_cmd_windows docstring that said the
Desktop never restarts the messaging gateway.

Closes #119809
This commit is contained in:
teknium1
2026-09-23 02:46:25 -07:00
committed by Teknium
parent d10f1735bc
commit 0f1544f903
3 changed files with 26 additions and 6 deletions

View File

@@ -794,7 +794,8 @@ def _windows_cold_start_plan() -> dict | None:
gateway that died without a clean exit. The Desktop hand-off exits the app before the updater starts
and can kill the running gateway in those same seconds, so discovery finds no live PID to pause
(#109538) — the dead attestation is the only surviving "a gateway was up" evidence, and the Desktop
does not restart the messaging gateway itself. Keep the plan, and record the attestation
only restarts gateways it stopped itself (its hand-off script, after the update verifies; #119809).
Keep the plan, and record the attestation
*generation* that authorized it on the token: the marker is a mutable one-shot that any concurrent
``hermes gateway status``/``start`` consumes, so execution authorizes the spawn from the token and
consumes only that generation (#110020 review)."""

View File

@@ -1198,6 +1198,8 @@ function Resolve-HermesVenvDir([string]$Root) {
}
$finalCode = 1
$manualAction = $false
$manualMsg = ""
$finalMsg = "update did not complete"
$script:TreeSafeToFinalize = $true
@@ -1688,10 +1690,13 @@ try {
if ($res.Code -eq 0 -and -not $desktopBuildFailed -and -not $NoGateway) {
$gatewayRestart = Invoke-HermesStep $pythonExe @("-m", "hermes_cli.main", "gateway", "start", "--all") "gateway restart"
if ($gatewayRestart.Code -ne 0) {
$finalCode = 9
$finalMsg = "Update completed, but Hermes could not restart every messaging gateway. Reopen Hermes and run `hermes gateway start --all` in a terminal."
Write-HandoffLog $finalMsg
exit $finalCode
# The update itself succeeded; a restart miss is a manual follow-up
# (Write-Result's manual flag -> Desktop boot dialog), never a failed
# update: a non-zero exit here would run the error finale and hide
# the fact that the new runtime is installed and verified.
$manualAction = $true
$manualMsg = "Update complete, but Hermes could not restart every messaging gateway. Run `hermes gateway start --all` in a terminal."
Write-HandoffLog $manualMsg
}
}
@@ -1726,7 +1731,8 @@ try {
Show-ErrorFinale $finalMsg
Close-ProgressWindow
} else {
Write-Result ($finalCode -eq 0) $finalCode $finalMsg
if ($finalCode -eq 0 -and $manualAction) { $finalMsg = $manualMsg }
Write-Result ($finalCode -eq 0) $finalCode $finalMsg ($finalCode -eq 0 -and $manualAction)
Remove-MarkerIfOwned
if ($finalCode -ne 0) {
Show-ErrorFinale $finalMsg

View File

@@ -58,3 +58,16 @@ def test_successful_local_update_restarts_all_gateways_after_verification() -> N
"-NoGateway must keep remote-served Desktop from starting a local "
"messaging gateway"
)
# The update has already succeeded when the restart runs: a restart
# failure surfaces as a manual follow-up (Write-Result's manual flag, the
# Desktop's boot dialog), never as a non-zero exit that reads as a failed
# update and triggers the error finale.
after_restart = source[source.index(restart):]
# The failure branch is the `if ($gatewayRestart.Code -ne 0) { ... }` block right
# after the step; the normal success finale that follows it is out of scope.
failure_branch = after_restart[: after_restart.index("if ($res.Code -eq 0 -and -not $desktopBuildFailed) {")]
assert "$manualAction = $true" in failure_branch
assert "$finalCode =" not in failure_branch, (
"a gateway restart failure must not rewrite the update's exit code"
)