Thanks to visit codestin.com
Credit goes to github.com

Skip to content

🤖 fix: allow server updates with recoverable watchers and newest npm builds - #4127

Merged
ibetitsmike merged 6 commits into
mainfrom
mike/server-updates-watchers-npm
Sep 8, 2026
Merged

🤖 fix: allow server updates with recoverable watchers and newest npm builds#4127
ibetitsmike merged 6 commits into
mainfrom
mike/server-updates-watchers-npm

Conversation

@ibetitsmike

Copy link
Copy Markdown
Contributor

Summary

Server self-updates no longer refuse to restart because of background bash jobs whose monitors will be recovered after the restart, and the server gains an npm update channel that follows the newest published package instead of dist-tags. A new integration harness drives the real install flow to prove the restart-blocker rules.

Background

Server-mode updates (update.install) take an idle snapshot before swapping the launcher. Any running background process counted as a blocker, so a workspace that had armed a long-lived monitored watcher (the normal agent pattern for dev servers and watch builds) could never update. Those watchers are safe to interrupt: their armed-monitor registration is durable, and after the restart the owning workspace receives a "Monitored background process lost" wake and can relaunch the job. Separately, the npm dist-tags used by the stable and nightly channels can lag a publication, so there was no way to follow the newest build.

Implementation

  • ServiceContainer.refreshRestartBlockers now asks WorkspaceService.getRestartSafeBashMonitors which running background monitors have a durable registry row for the same arm generation (same createdAt, not terminal, not lost). Only those are exempt in BackgroundProcessManager.getRestartBlockingProcessCount; foreground bash, stopped monitors, failed or stalled registry writes, and registry read failures or timeouts (1 s) all fail closed and keep blocking. The registry is read without draining pending writes on purpose: a stalled arm write must still block.
  • npm channel (server only): fetchNewestVersion picks the newest exact version by publish time from the packument. UpdateService.getSupportedChannels exposes what the current build supports; Electron reports stable/nightly only, maps a persisted npm preference to stable, and rejects selecting it. update.getChannel returns { channel, supportedChannels } and the About dialog renders the toggle from that list.

Validation

  • tests/ipc/serverUpdateRestartBlockers.test.ts runs the real ServiceContainer, update IPC, bash tool spawn (never-matching monitor), PTY terminal, registry store, and product termination path: a terminal opened while blockers are being prepared still blocks the install (raw install-blocked payload lists only terminals), closing it makes a restart-free retry succeed; a job whose registry write failed blocks (background-processes), a product-driven stop clears it, a fresh durable monitor is exempt, and a second container over the same root schedules recovery for the surviving row. Each of four production mutations (drop terminal count, count every process, trust in-memory monitors, skip the refresh) turns the harness red.
  • Remote UAT (Coder Agents, rounds 3 to 5) on the exact SHAs covered the real-model UI install flow, post-restart watcher recovery, channel ordering and persistence, Electron gating, and 375px layout.

Risks

Restart gating is the safety boundary for self-updates. The change only narrows blocking for one precisely identified class (running, non-foreground, armed and unstopped monitor with a matching durable row); every uncertainty path keeps blocking. The npm channel can select pre-releases by design; it is opt-in and server-only.


Generated with xum • Model: anthropic:claude-fable-5-1 • Thinking: xhigh • Cost: $12.56

@mintlify

mintlify Bot commented Sep 8, 2026

Copy link
Copy Markdown

Preview deployment for your docs. Learn more about Mintlify Previews.

Project Status Preview Updated
Mux 🟢 Ready View Preview Sep 8, 2026, 9:08 AM

💡 Tip: Enable Automations to automatically generate PRs for you.

@ibetitsmike

Copy link
Copy Markdown
Contributor Author

@codex review

@chatgpt-codex-connector

This comment has been minimized.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 71762ab3d9

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/browser/features/About/AboutDialog.tsx
Comment thread src/node/services/workspaceService.ts
@chatgpt-codex-connector

This comment has been minimized.

@ibetitsmike

Copy link
Copy Markdown
Contributor Author

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. 🚀

Reviewed commit: 1a99389e1b

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@ibetitsmike
ibetitsmike marked this pull request as ready for review September 8, 2026 10:09
@ibetitsmike
ibetitsmike added this pull request to the merge queue Sep 8, 2026

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 1a99389e1b

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

{ timeoutMs: SERVER_UPDATE_MONITOR_VERIFY_TIMEOUT_MS }
);
if (result.kind === "ok") {
const records = new Map(result.value.flat().map((record) => [record.processId, record]));

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Key registry rows by workspace and process

When a stale recovery row in one workspace shares a display-derived process ID with a current monitor in another workspace, and both workspaces also have live monitors, flattening all rows into a map keyed only by processId lets the stale row overwrite the current row depending on workspace iteration order. The ownership check then rejects the otherwise durable monitor, so background-processes continues blocking the server update until unrelated recovery completes; key the lookup by both owner workspace and process ID.

AGENTS.md reference: AGENTS.md:L10-L11

Useful? React with 👍 / 👎.

Comment on lines +2393 to +2397
process.monitor.pendingLines.length === 0 &&
process.monitor.retainedMatches.length === 0 &&
durableMonitorGenerations?.get(process.id) === process.monitor.armMetadata.createdAt
) {
continue;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Do not exempt monitors that cannot be terminated

When a monitored process runs through an unreachable SSH/Coder runtime, list() treats a failed exit-code probe as still running and this condition exempts it solely because its local registry row is durable. During restart, RuntimeBackgroundHandle.terminate() also swallows remote command failures, after which the manager marks the process killed and clears it; the detached remote process therefore survives while recovery reports it as lost and may prompt the agent to launch a duplicate. Keep remotely unverifiable monitors blocking, or require confirmed termination before activating the update.

AGENTS.md reference: AGENTS.md:L10-L11

Useful? React with 👍 / 👎.

Merged via the queue into main with commit 0d078d1 Sep 8, 2026
20 of 21 checks passed
@ibetitsmike
ibetitsmike deleted the mike/server-updates-watchers-npm branch September 8, 2026 10:31
yermakoffivan pushed a commit to yermakoffivan/mux that referenced this pull request Sep 9, 2026
## Summary

Version bump for the v0.28.5 patch release. Headline changes since
v0.28.4: remote server connections in the desktop app (coder#4101),
self-updating `xum server` under a restart supervisor (coder#4083, coder#4127),
first-class GPT-6 Astra and Astra Pro support including Codex OAuth
routing (coder#4064, coder#4094, coder#4106, coder#4124), token-budget context window
rollovers (coder#4097), the workspace remembering model and mode on send
(coder#3968), in-place plugin updates (coder#4164), the optional flat sidebar chat
list (coder#3994), and copying selected chat text as Markdown (coder#4170). It
also carries a long run of streaming, compaction, and task-lifecycle
fixes (reconnect streaming coder#4123, message edits during active streams
coder#4153, Codex OAuth prompt-cache routing coder#4159, compaction/history
fencing coder#4133 through coder#4148, task lock ordering coder#4161) plus the Effect
Wave 4 runtime refactors and deslop passes 1 through 3.

## Implementation

Bumped with `node ./scripts/set-package-version.js 0.28.5` so the root
`package.json` and the legacy `packages/mux-compat` forwarding package
stay version-locked. `src/common/compat/productIdentity.test.ts` passes
locally (8/8).

After this PR merges, the `v0.28.5` tag will be applied to the squash
commit and the GitHub Release published to trigger the
desktop/npm/docker pipelines.

---

_Generated with `xum` • Model: `anthropic:claude-fable-5-1` • Thinking:
`xhigh` • Cost: `$1.64`_

<!-- mux-attribution: model=anthropic:claude-fable-5-1 thinking=xhigh
costs=1.64 -->
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant