cmux NEXT: See What's New opens the What's New tab again
Leo, 2026-10-29: "And why the f*** does See What's New not fing open the What's New tab anymore? Why does it not fing open anything on the f***ing right?"
What broke it
- #26138 (
fb25b906b22, "hide App Store and What's New by default") made the changelog page (What's New) a Labs preview. Whilelabs.previewFeaturesis off (the default),InternalPageTabStore.show/openNew, both tabviewpaths,TopPageHost.viewand the pane strip all return nil or hide it for.changelog. cf39c17d627(a direct push, "What's New shows after every update by default (no Labs gate)", user 13935) brought back the "cmux Updated!" card and update island with Labs off. It removed the gate from theopenChangelog/openChangelogSpanclosures but not from the page.- So clicking See What's New calls
openWhatsNewForLastUpdate→ChangelogPageTab.open→services.pages.show(.changelog, …). That still returns nil, so nothing opens. The sidebar card's button had a second problem: it ran the palette'supdates.whatsNew, which is unavailable while Labs is off.
Fix
- The Labs preview gate now covers only the App Store. Every gate site uses one predicate,
InternalPageTabStore.isPreviewPage, instead of repeatingpage == .appStore || page == .changelog. - The "cmux Updated!" card's See What's New now calls
UpdaterService.openWhatsNewForLastUpdate(), the same call the update island's button makes. It no longer goes through the palette action. - The palette and Help menu "What's New" entry (
updates.whatsNew) stays a Labs preview, unchanged from #26138. No default is flipped.
Risk: small. A restored What's New tab now stays in the strip with Labs off.
Tests (red/green)
3f21f88cc6e adds the first tests on the broken code. 144331ced3d is the fix. d35263084db and 08327e35ad0 answer the review:
LaunchPolishVisibilityTests/whatsNewPageIsNotALabsPreviewPageButTheAppStoreIsLaunchPolishVisibilityTests/updatedCardSeeWhatsNewOpensTheUpdatesSpanWithoutThePaletteAction: seeds the last update (0.9.0 to 1.0.0). With noupdates.whatsNewbound, the card's See What's New must open that span.LaunchPolishVisibilityTests/updatedToastSeeWhatsNewOpensTheUpdatesSpan: the update toast'scmux.changelog.surface.openChangelogopens the same span.LaunchPolishVisibilityTests/theUpdatesSpanIsTheChangelogTabsRoute: the span becomes the tab's#/?from=0.9.0&to=1.0.0.RestoredInternalPageTabTests/restoredPreviewPagesWaitForThePreviewSetting(now App Store only), plus a newaRestoredWhatsNewTabRestoresWithLabsOff.PreviewPageTabVisibilityTests/previewPageTabsFollowLabsWithoutARefresh(updated): with Labs off, App Store tabs leave the strip and What's New tabs stay.
WhatsNewCenter.lastUpdate's setter goes from private(set) to internal(set), only so the tests can seed it. No behavior change.
Fleet runs (scripts/ci/package-test-lane.sh suite Packages/macOS/CmuxNext ...):
- Red, tests only at
3f21f88cc6e(stepb6335883754032009a0fdd8b, aws-m4pro-1): all three first tests fail.opened → 0 == 1;isPreviewPage("changelog") → true;ids().contains(storedChangelogID) → false. - Green, the fix at
144331ced3d(step04d6ac72676610ba0ff03e7d): both suites pass, 6/6. - Head
08327e35ad0, LaunchPolishVisibilityTests, PreviewPageTabVisibilityTests and RestoredInternalPageTabTests (step13bbeea2106b2397a6669604): all 3 suites pass, 7 + 1 + 7 tests. The step atd35263084db(a05851d9ee47a00593e8a6ff) crashed after the toast test passed: the test builtAppServicesbeforeNSApplication.shared, and08327e35ad0fixes that.
Capture
The steps (one fleet build per commit, driven on a capture mini, Labs off):
debug.updater {action: "updated", previous: "0.0.1"}shows the Updated card.debug.update_surfaces {action: "open-whats-new"}is the update toast's See What's New (openWhatsNewForLastUpdate).
Before, at base c00c3219338a: the click returns false and nothing opens on the right.
| Light | Dark |
|---|---|
![]() | ![]() |
After, at 144331ced3d7: the click returns true and the What's New tab opens on the right. d35263084db and 08327e35ad0 change only tests and one setter's visibility.
| Light | Dark |
|---|---|
![]() | ![]() |
Agent session: agent session
🤖 Generated with Claude Code



