Skip to content

cmux NEXT updater: Restart to Update installs the newest build; a pulled build is dropped, never offered - #27499

Merged
teamleaderleo merged 27 commits into
feat-cmux-nextfrom
fix-next-updater-latest
Oct 31, 2026
Merged

teamleaderleo merged 27 commits into
feat-cmux-nextfrom
fix-next-updater-latest

Conversation

@teamleaderleo

@teamleaderleo teamleaderleo commented Oct 29, 2026 •

Copy link
Copy Markdown
Collaborator

Leo (2026-10-29): "those kinds of download/update things need to be more "latest" instead of me downloading whatever was the first one... but if there's multiple nightlies, i should only need to do one to get the latest"

Leo (2026-10-29), on the pulled-build banner: "what the f*** is this nightly was pulled, and why the f*** are the buttons like that? ... what the f*** does this nightly was pulled even fing mean? The rollback. I mean, why the f was it pulled? Like, why the f*** am I even getting a thing that I can download that I can just— that was pulled in the first place? Just f***ing cancel it, or, like, do something else about it. Just don't have that be the downloading thing."

Before: the sidebar showed "This Nightly Was Pulled" with Wait for the Fix and Roll Back (Leo's screenshot, not reproduced here).

After (the running build was pulled; the same card without the second line shows while Restart to Update fetches a newer build):

Capture tour-update-newest at e99ac550f29b (fleet build, capture mini, text checked for private data)

Light Dark
light dark

Viewed after image: yes
Visual verdict: The sidebar footer card reading Getting the Newest Build with its pulled-build note and progress bar sits cleanly in light and dark, and it is unchanged at 15fffb8b since the port only hides cards for a held pulled build.

Takes back #25725: nothing of its behavior. This PR rewrites PulledBuildWatchTests (which #25725 extended for the Updated card's pulled-build count) because the banner those tests covered is removed. pulledBuilds and the Updated card's use of it stay, and theWatchReadsTheListAndTheRunningBuildsEntry still checks that every pulled build is read.

Changelog

Fixed: Restart to Update installs the newest build on the feed, and a pulled build is never offered.

What happened

Nightly 4091813159501 was staged at 18:16Z. By 18:19Z the feed already listed 4092299464301. Restart to Update installed the stale 4091813159501 anyway. That build was then pulled (it crashed in the fresh-home smoke), so the app showed "This Nightly Was Pulled" with Wait for the Fix and Roll Back, and a second update was needed.

The click already re-read the feed before installing (StagedUpdateRefresh.beforeInstall), but only when found updates download by themselves. Nightly asks before it downloads (updates.downloadAutomatically is off by default), so on the default setup the click never re-read the feed.

Change

  • Restart to Update always ends on the newest build. The click re-reads the feed and pulled.json whether downloads are automatic or not. The feed has the existing 3 s deadline; a staged build is never installed before pulled.json answers (each read has a 15 s request timeout), and only a newer build this app can swap to settles the click sooner. If pulled.json cannot be read at all, the click installs, as before: the list is the only word that a build was pulled. The click itself is the person's yes to the download. If the feed has a strictly newer build, or the staged build was pulled, the staged installer is cancelled and the newest build downloads with no second click. The click carries over and installs it once it is staged. The notice card reads "Getting the Newest Build…" with progress and no buttons.
  • A pulled staged build is dropped quietly and the newest good build downloads in its place. The Update Ready card then asks before the relaunch, as every update does. Each pulled build is dropped only once (a cached appcast that stages it again is dropped without another fetch), so nothing loops.
  • A pulled running build fetches and downloads the newest good build, once per launch. The card says one line: "This build was pulled." The relaunch still asks. With nothing newer on the feed, nothing shows.
  • Removed: the "This Nightly Was Pulled" card, its Wait for the Fix and Roll Back buttons, the rollback wiring and its strings. The palette and menu's "Roll Back to Previous Version…" stays.
  • The CI side is a separate PR: the fresh-home smoke gates the appcast write, so a build that fails it is never offered.

Stop condition and cleanup: newestFetch ends when the newest build is staged, when the check ends with nothing or fails, or when an install starts. No timer and no polling: the logic runs when the pulled list is read (launch, each update cycle, the click) and when a build is staged or found.

Carry fixes (review BLOCKs at b361383 and a3718b9)

Carried after the owning session ended, red tests first (UpdatePulledEdgesTests; red at 5830032, 0e10b7d, ed9cb0d, 78611ce, e8b2f6c, 48594c9 (BackgroundInstallTests) and cdd861f (PulledBuildWatchTests); green at c7e8278):

  • A pulled list slower than the click's 3 s deadline no longer loses a newer build: the deadline settles on the feed's answer, and a pulled answer that arrives later still settles the click.
  • With an installer this app cannot cancel (Sparkle's own driver), every click reads the pulled list first, and a pulled staged build is never installed; the update sheet opens instead.
  • The click waits for the pulled list before installing, judges the build staged when it settles (Sparkle may stage another while it waits), and with no cancellable installer never installs before the list answers.
  • A pulled running build the list reports while a check runs is followed once that check ends, and a legacy feed's two pulled lists are read at once.
  • Ported from the parallel carry cmux NEXT updater: Restart to Update installs the newest build; a pulled build is dropped (carries #27499) #28074: Sparkle's driver dismisses a known-pulled found build before any download or prompt (UpdateController.refusesUpdate), and a pulled running build still updates past a pulled staged build no one can cancel.
  • A staged build known pulled that this app cannot cancel shows no card, footer pill or ready card (also after a check the person asks for).
  • A found build that is already known pulled is never offered as "Update Available" and never downloads, also when downloads ask.
  • A carried fetch for the newest build ends when a pulled found build is dismissed, so "Getting the Newest Build…" never stays up.

Tests (fleet, cmux-ci run package-test-lane.sh suite)

At head c7e8278 (fleet steps 8f461828 and the CmuxUpdater BackgroundInstallTests run): UpdatePulledEdgesTests, UpdateClickInstallsNewestTests, PulledBuildWatchTests, UpdateAsksBeforeInstallTests, UpdateReadyNotNewerTests and UpdateInstallStatusTests pass. Earlier heads also passed SidebarCardSurfaceTests.

UpdateStagedYieldsToNewerTests and TipUpdateCheckTests fail at this head only in tests that also fail on base e219b3a (fleet step 6f10f824) with the same assertions (h.feed.fetches counts and tipCheck.timer.isScheduled), and at this PR's original head b361383 (step 32fb9aab). They are not from this PR.

  • UpdateClickInstallsNewestTests.withDownloadsAskingOneClickStillInstallsTheNewestBuild covers the case from Leo's Mac: 300 staged, 500 on the fake appcast, downloads asking. One click cancels 300, shows "Getting the Newest Build…", downloads 500 and installs it once staged.
  • UpdateClickInstallsNewestTests.aClickNeverInstallsAPulledStagedBuild
  • PulledBuildWatchTests covers: the quiet swap of a pulled staged build, no loop when it is staged again, the one-line update of a pulled running build, and a quiet end when nothing is newer.

Observed / Not run

Observed: the suites above pass on the fleet at this branch (one run showed UpdateStagedYieldsToNewerTests.aScheduleChangeReplacesThePendingProbe failing once; see the comment below for the rerun). The capture above is a fleet build driven on a capture mini.
Not run: the new click test on base (it uses the cancellable and pulled-list seams this PR adds). By reading, base's beforeInstall returns install() at once when downloadsUpdatesInBackground is false, the nightly default. No live install against the real feed.

Risk: high (updater). It changes the install click's path when downloads ask, and removes a card. The existing click and staged-refresh suites still cover the automatic-download path.

After #28074

#28074 landed this PR's first part on feat-cmux-next (the click reads the feed, a pulled staged build is dropped, a pulled running build updates). This PR now carries only the remaining edge fixes on top of it, merged with base's updater as the foundation:

  • The install click reads the pulled list even with no installer it can cancel, never installs a staged build before the list answers (only a newer build it can swap to settles the click sooner), and judges the build staged now.
  • A pulled running build read while a check runs is followed when the check ends.
  • The legacy feed's two pulled lists are read at once.
  • A staged build known pulled that no installer can drop shows no card, footer pill or Update Ready card. A quit cancels it instead of installing it when this app holds its installer; while Sparkle's silent cycle still owns the installer (the same window base has), nothing can cancel it, so the quit proceeds and the log says Sparkle installs it (15fffb8b; red at 69cfba14, fleet step e77984d7da5c0d4898060387; green at 15fffb8b with PulledBuildWatchTests and UpdateClickInstallsNewestTests, step 094ee35676f90668c3c664f7).

Red/green: UpdatePulledEdgesTests on base df9b52b7 failed 7 of 10 (fleet step e615cb37eb6282d90c7c9144); at d3ee6669 it passes with PulledBuildWatchTests, UpdateClickInstallsNewestTests and ReleasePushListenerTests (step 1950f9f569021aabfadd5553) and CmuxUpdater BackgroundInstallTests (step a2e995b7bdacad2ea5797425). UpdateStagedYieldsToNewerTests and TipUpdateCheckTests fail on base 00f9b034 with the same tests (step 25fefa55cec8a2b85c076ef6); aScheduleChangeReplacesThePendingProbe flips on base too (step fd0843a948e415f92b4033dd) and passed at d3ee6669 on a rerun (step 10b7798b17b91e9805f3686f).

Agent session: agent session

🤖 Generated with Claude Code

…led build is dropped, never offered

The install click re-reads the feed and the pulled list whether or not found
updates download by themselves (nightly asks before it downloads, so the click
installed whatever was staged first). A newer build or a pulled staged one gives
way and the newest downloads with no second click ("Getting the Newest Build…").
A pulled staged build is dropped quietly and the newest good build downloads; a
pulled running build updates to the newest good one with one line. The "This
Nightly Was Pulled" banner, Wait for the Fix and Roll Back are removed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?id=aid-72a66988b5244633adf9
@teamleaderleo

teamleaderleo commented Oct 29, 2026 •

Copy link
Copy Markdown
Collaborator Author

Owned by an agent session · took over from an earlier session · session

@github-actions

github-actions Bot commented Oct 29, 2026 •

Copy link
Copy Markdown
Contributor

Default changes

No defaults change at 15fffb8be725.

@github-actions github-actions Bot added the risk:high Risk tier (docs/ci/risk-tiers.md) label Oct 29, 2026
@teamleaderleo

Copy link
Copy Markdown
Collaborator Author

Bead cx-0at8bm created for this PR by the cmux coordinator.

…nnot be cancelled or it is staged again; keep the rollback confirmation's Roll Back string

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?id=aid-72a66988b5244633adf9
@blacksmith-sh

blacksmith-sh Bot commented Oct 29, 2026 •

Copy link
Copy Markdown

Found 12 test failures on Blacksmith runners:

Failures

Test View Logs
/tmp/tmp1ny8telj/summary-missing.json (live):/summary-missing.json (live): View Logs
/tmp/tmpnawdfa_r/summary-fail.json (live):/summary-fail.json (live): View Logs
[new_workspaces] debug.new_workspace timed 0 of 50 new workspace rows/
[new_workspaces] debug.new_workspace timed 0 of 50 new workspace rows
View Logs
[new_workspaces] the window draws no frames/[new_workspaces] the window draws no frames View Logs
[tabs] debug.tab_switch timed 0 of 40 switches/
[tabs] debug.tab_switch timed 0 of 40 switches
View Logs
[tabs] the window draws no frames/[tabs] the window draws no frames View Logs
main.DeveloperIdAppTests.test_download_prints_the_active_profile_only/
test_download_prints_the_active_profile_only
View Logs
stubs: /System/Library/Frameworks/Security.framework/Versions/A/Security has no stub/
Security has no stub
View Logs
stubs: CoreFoundation.tbd: install-name /System/Library/Frameworks/
CoreFoundation.framework/Versions/A/CoreFoundation, missing 1: ['_CFRetain']/
CoreFoundation, missing 1: ['_CFRetain']
View Logs
stubs: CoreFoundation.tbd: install-name /System/Library/Frameworks/
CoreFoundation.framework/Versions/A/CoreFoundation, missing 1: ['_log2']/
CoreFoundation, missing 1: ['_log2']
View Logs

...and 2 more test failures. View all on Blacksmith

Fix with [code]smith
Need help on this PR? Tag @codesmith-bot with what you need.

@github-actions

github-actions Bot commented Oct 29, 2026 •

Copy link
Copy Markdown
Contributor

cmux status (one comment, edited in place; each line is updated by the job that owns it)

Review 15fffb8: HQ feed card · gallery before/after runs · checks

App of this head (app.zip, kept 1 day)

gh workflow run reload-build.yml -R manaflow-ai/cmux --ref feat-cmux-next -f tag=pr27499 -f ref=fix-next-updater-latest -f platform=macos -f backend_mode=local

web and size checks: green

Shipped in:

@teamleaderleo
teamleaderleo force-pushed the fix-next-updater-latest branch from b5627db to e5a1f4b Compare October 29, 2026 19:02
@teamleaderleo
teamleaderleo marked this pull request as ready for review October 29, 2026 19:09
…uild card; a What's New highlight

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?id=aid-72a66988b5244633adf9
…side the Sendable fetch

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?id=aid-72a66988b5244633adf9
@teamleaderleo

Copy link
Copy Markdown
Collaborator Author

Base comparison for the one red in the focused fleet run: UpdateStagedYieldsToNewerTests.aScheduleChangeReplacesThePendingProbe (h.sparkle.cancels → 2 == 1) and theNewestStagedBuildIsKeptAndProbedOncePerInterval (h.feed.fetches → 2 == 1) fail the same way at the base a653ee3 (3 runs of the suite: 2 failed, one with each test). They are a timing flake on base and not this PR's. The other suites pass at head and base. This PR's own suites (PulledBuildWatchTests, UpdateClickInstallsNewestTests) pass at head.

@teamleaderleo

Copy link
Copy Markdown
Collaborator Author

Review (Codex gpt-6-astra, high, fast; independent, correctness first): SHIP at e99ac55

Rounds: BLOCK at 277a98d (a carried click could reach a pulled build staged again; a failed cancel installed a pulled build), BLOCK at d6687af (a failed pulled.json read forgot a pulled build), BLOCK at da479c8 (a partial two-list read did too), SHIP at e5a1f4b, SHIP at e99ac55 for the delta (debug hook, tour, highlight, test compile fix).

@teamleaderleo

Copy link
Copy Markdown
Collaborator Author

@teamleaderleo The draft carry #28120 at 631e3d9 includes the previously relayed installer repairs and keeps pendingClick while a pulled-list refresh is in flight at the feed deadline. Do you agree to this carry superseding #27499, or would you rather fold the fixes into your branch? It stays a draft until you agree; no fleet runs or close are requested.

teamleaderleo and others added 2 commits October 30, 2026 05:42
…gacy feed's two lists

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?id=aid-0cf32b32a03b27dcdf4d
…ad the legacy feed's lists at once

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?id=aid-0cf32b32a03b27dcdf4d
@teamleaderleo

Copy link
Copy Markdown
Collaborator Author

Review (codex gpt-6.1-sol high, review-router): SHIP at b5ced95. No findings. Carried fixes for the BLOCKs at ded3cb9, a6a3954 and 3ac93b5 (each with a red test first). Fleet at this head: UpdatePulledEdgesTests, UpdateClickInstallsNewestTests, PulledBuildWatchTests, UpdateAsksBeforeInstallTests, UpdateReadyNotNewerTests, UpdateInstallStatusTests pass (step a1e1ee2a).

teamleaderleo and others added 2 commits October 30, 2026 06:54
…ered

From #28074 (lane/odd-27499-updater), a parallel carry of this PR.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?id=aid-0cf32b32a03b27dcdf4d
…any download or prompt

Ported from #28074 (lane/odd-27499-updater): with automatic downloads a pulled
found build no longer downloads only to be dropped once staged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?id=aid-0cf32b32a03b27dcdf4d
teamleaderleo and others added 2 commits October 30, 2026 06:56
…ged build cannot be dropped

From #28074 (lane/odd-27499-updater).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?id=aid-0cf32b32a03b27dcdf4d
…ld no one can cancel

Ported from #28074 (lane/odd-27499-updater).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?id=aid-0cf32b32a03b27dcdf4d
teamleaderleo added a commit that referenced this pull request Oct 30, 2026
…eview

- UpdateClickInstallsNewestTests.aFeedThatAnsweredDecidesWhileThePulledListIsSlow:
  the feed answers with a newer build at once while the pulled list is read past the
  click's deadline; the stale staged build must not install.
- UpdateClickInstallsNewestTests.aKnownPulledStagedBuildIsNotInstalledWhenTheClickCannotReplaceIt:
  with no installer this app can cancel, a known-pulled staged build must not install.
- PulledBuildWatchTests.aFoundPulledBuildIsNeverOfferedOrDownloaded: with downloads
  asking first, a known-pulled found build shows no card or button and never downloads.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?id=aid-f050dc5d5c747badec51
teamleaderleo added a commit that referenced this pull request Oct 30, 2026
…eview

- UpdateClickInstallsNewestTests.aFeedThatAnsweredDecidesWhileThePulledListIsSlow:
  the feed answers with a newer build at once while the pulled list is read past the
  click's deadline; the stale staged build must not install.
- UpdateClickInstallsNewestTests.aKnownPulledStagedBuildIsNotInstalledWhenTheClickCannotReplaceIt:
  with no installer this app can cancel, a known-pulled staged build must not install.
- PulledBuildWatchTests.aFoundPulledBuildIsNeverOfferedOrDownloaded: with downloads
  asking first, a known-pulled found build shows no card or button and never downloads.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?id=aid-f050dc5d5c747badec51
@teamleaderleo

Copy link
Copy Markdown
Collaborator Author

Review (codex gpt-6.1-sol high, review-router): SHIP at c7e8278. No P1/P2 findings. Adds two ports from #28074 (refusesUpdate in CmuxUpdater; a pulled running build updates past an uncancellable pulled staged build), each with a red test (48594c9, cdd861f). Fleet at this head: BackgroundInstallTests and the six updater suites pass (step 8f461828).

teamleaderleo added a commit that referenced this pull request Oct 30, 2026
…led build is dropped (carries #27499) (#28074)

* cmux NEXT updater: Restart to Update installs the newest build; a pulled build is dropped, never offered

The install click re-reads the feed and the pulled list whether or not found
updates download by themselves (nightly asks before it downloads, so the click
installed whatever was staged first). A newer build or a pulled staged one gives
way and the newest downloads with no second click ("Getting the Newest Build…").
A pulled staged build is dropped quietly and the newest good build downloads; a
pulled running build updates to the newest good one with one line. The "This
Nightly Was Pulled" banner, Wait for the Fix and Roll Back are removed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?id=aid-72a66988b5244633adf9

* cmux NEXT updater: never install a pulled build when its installer cannot be cancelled or it is staged again; keep the rollback confirmation's Roll Back string

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?id=aid-72a66988b5244633adf9

* cmux NEXT updater: a failed pulled-list read never forgets a pulled build

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?id=aid-72a66988b5244633adf9

* cmux NEXT updater: a pulled build stays pulled for the life of the process

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?id=aid-72a66988b5244633adf9

* cmux NEXT updater: a debug hook and tour for the Getting the Newest Build card; a What's New highlight

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?id=aid-72a66988b5244633adf9

* cmux NEXT updater tests: the two-list pulled test reads its lists outside the Sendable fetch

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?id=aid-72a66988b5244633adf9

* cmux NEXT media: the update-newest tour ends on the card, so the stills show it

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?id=aid-72a66988b5244633adf9

* release notes: the newest-build highlight offers Check for Updates

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?id=aid-72a66988b5244633adf9

* cmux NEXT updater: regression tests for the three P2s of the #27499 review

- UpdateClickInstallsNewestTests.aFeedThatAnsweredDecidesWhileThePulledListIsSlow:
  the feed answers with a newer build at once while the pulled list is read past the
  click's deadline; the stale staged build must not install.
- UpdateClickInstallsNewestTests.aKnownPulledStagedBuildIsNotInstalledWhenTheClickCannotReplaceIt:
  with no installer this app can cancel, a known-pulled staged build must not install.
- PulledBuildWatchTests.aFoundPulledBuildIsNeverOfferedOrDownloaded: with downloads
  asking first, a known-pulled found build shows no card or button and never downloads.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?id=aid-f050dc5d5c747badec51

* cmux NEXT updater: a pulled build never installs or shows, and a prompt feed answer decides the click

- StagedUpdateRefresh.beforeInstall: the probe and the pulled-list read are tracked apart.
  A probe that finds a strictly newer build decides the click at once, and when the
  deadline fires, a probe that already answered still counts, so a slow pulled list no
  longer installs the stale staged build.
- StagedUpdateRefresh.beforeInstall: when the click cannot replace the staged build (no
  cancellable installer, updates disabled), a known-pulled staged build is not installed;
  the update sheet opens instead, as for the pulled/no-installer case.
- A found build known pulled (UpdaterService.isKnownPulled) is no update: indicatorPhase
  hides it (no card, no Update Available button, no download through the gate), its
  Sparkle prompt is dismissed without skipping (dropPulledAvailable), and followPulled
  takes it off the update-found step when the pulled list marks it later.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?id=aid-f050dc5d5c747badec51

* cmux NEXT updater: regression tests for the two P1s of the #28074 review

- BackgroundInstallTests.aRefusedBuildIsNeitherDownloadedNorOffered: a build the host
  refuses (a pulled build) is not accepted by the background download, not shown as a
  prompt, and not downloaded by acceptAvailableUpdate.
- PulledBuildWatchTests.aPulledRunningBuildStillUpdatesWhenAPulledStagedBuildCannotBeDropped:
  running and staged builds both pulled, the staged cancel fails: the newest-build check
  still starts, once.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?id=aid-f050dc5d5c747badec51

* cmux NEXT updater: a pulled build never downloads, and a pulled running build updates past a kept pulled staged one

- CmuxUpdater: UpdateController.refusesUpdate lets the host refuse a found build by its
  sparkle:version. The driver dismisses a refused build when it is found, before the
  background accept (so automatic downloads never download it) and before any prompt,
  and acceptAvailableUpdate never downloads one. UpdaterService refuses known-pulled builds.
- followPulled: when the running and staged builds are both pulled and the staged
  installer cannot be cancelled, the running-pulled branch still starts the newest-build
  check (once per launch, runningPulledHandled); an install click still decides for itself.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?id=aid-f050dc5d5c747badec51

* test: recover from silent staged updater before newest check

Agent-Session: https://cmux.com/deeplink/agent?id=aid-95068e576a81797e98a3

* fix: replace stale silent updater before newest check

Agent-Session: https://cmux.com/deeplink/agent?id=aid-95068e576a81797e98a3

* test(updater): expose pulled-policy and silent installer races

Exercise a fast appcast while the pulled-list read is held, and resume and cancel Sparkle silent staging through the real controller. Before the fix the appcast is accepted early and the silent installer stays uncancellable.

Agent-Session: https://cmux.com/deeplink/agent?id=aid-95068e576a81797e98a3

* fix(updater): await pulled policy and resume silent installs for cancellation

Launch and appcast acceptance wait for the bounded pulled-list read. Return NO from the legacy silent-install callback, then resume through the foreground driver after Sparkle ends that cycle so its Skip reply cancels the actual installer. Do not clear only the model while a private Sparkle installer survives. Controller-level regressions cover both paths; fleet red and green receipts are recorded in the PR.

Agent-Session: https://cmux.com/deeplink/agent?id=aid-95068e576a81797e98a3

* test(updater): cover cancelled offers and managed recovery

A cancelled async policy read must not resurrect an appcast. Legacy silent recovery must cancel and enter a fresh foreground cycle before holding the ready reply, so quitting does not skip a good version. Automatic pulled recovery must honor the managed channel.

Agent-Session: https://cmux.com/deeplink/agent?id=aid-95068e576a81797e98a3

* fix(updater): invalidate cancelled offers and preserve update policy

Bind asynchronous offer preflight to the current check generation. Cancel legacy silent installers immediately when resumed, then enter a fresh foreground cycle: Sparkle 2.10 clears skipped state for a user-initiated check, so ordinary staged cancellation holds only the ready reply and never skips a good version. Automatic pulled recovery honors the managed channel, including a policy change during recovery.

Agent-Session: https://cmux.com/deeplink/agent?id=aid-95068e576a81797e98a3

* test(updater): preserve the running-pull explanation during staged replacement

Agent-Session: https://cmux.com/deeplink/agent?id=aid-95068e576a81797e98a3

* fix(updater): explain a pulled running build while replacing its staged installer

Agent-Session: https://cmux.com/deeplink/agent?id=aid-95068e576a81797e98a3

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…ge fixes onto it

#28074 landed this PR's first part. The merge takes base's updater and tests,
and keeps only the fixes base lacks, each pinned by UpdatePulledEdgesTests
(7 of its 10 tests fail on base df9b52b, fleet step e615cb37eb6282d90c7c9144):
- the install click reads the pulled list even with no installer it can cancel,
  never installs a staged build before the list answers (only a newer build it
  can swap to settles the click sooner), and judges the build staged now;
- a pulled running build read while a check runs is followed when it ends;
- the legacy feed's two pulled lists are read at once;
- a staged build known pulled that no installer can drop shows no card, footer
  pill or Update Ready card, and a quit cancels it instead of installing it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?id=aid-0cf32b32a03b27dcdf4d
teamleaderleo and others added 2 commits October 30, 2026 13:51
…held

Sparkle's silent cycle can still own the installer while it resumes; then
prepareForQuit no longer reports .cancelPendingInstall for a cancel that
did not happen, and its log says Sparkle installs the build on quit.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?id=aid-0cf32b32a03b27dcdf4d
@cursor

cursor Bot commented Oct 30, 2026

Copy link
Copy Markdown

Bugbot needs on-demand usage enabled

Bugbot uses usage-based billing for this team and requires on-demand usage to be enabled.

A team admin can enable on-demand usage in the Cursor dashboard.

@teamleaderleo

Copy link
Copy Markdown
Collaborator Author

Review (codex gpt-6.1-sol high, review-router): SHIP at 15fffb8

No P1/P2. One P3 (the body claimed a quit always cancels a pulled staged build) is fixed in the body.

@teamleaderleo
teamleaderleo merged commit 867e291 into feat-cmux-next Oct 31, 2026
256 of 269 checks passed
@teamleaderleo
teamleaderleo deleted the fix-next-updater-latest branch October 31, 2026 02:44

This branch was previously deployed

1 inactive deployment
ci-routing-agent — 15fffb8b Deployed Oct 30, 2026 by teamleaderleo via cmux-tui tree preflight #85038
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

risk:high Risk tier (docs/ci/risk-tiers.md)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant