From f4dea165703c1bd0616144e1783c00b6edf7cd54 Mon Sep 17 00:00:00 2001 From: Leo Li Date: Mon, 19 Oct 2026 07:00:08 +0000 Subject: [PATCH 01/26] test(changelog): What's New gallery ranges and a failing pre-publish notes check Gallery entries for an update of 1 nightly (3 changes), 10 (92), 49 (about 1,600 commits), one with only internal work and one with summary lines only, all from the 50 nightlies the nightly-next notes index lists today. Failing tests for what those ranges showed and for the gate: - "(hq#1957)" and "(review)" stay in titles; base reds and compile fixes read as changes a person would notice; the page and the pipeline read hq# references differently. - The update card and popup show a cut digest title, a work-stream line and a title repeated as its description from notes published before #21873. - checkNightlyNotes (stub) finds nothing; the command passes everything. Co-Authored-By: Claude Opus 5.5 --- scripts/cmux-next/check-release-notes.ts | 1 + .../src/pages/changelog/changelog.gallery.ts | 32 + .../changelog/fixtures/nightly-next-50.json | 7784 +++++++++++++++++ webviews/src/pages/changelog/notesCheck.ts | 13 + webviews/test/changelog-notes-check.test.ts | 114 + webviews/test/changelog-readable.test.ts | 33 +- webviews/test/update-ready-popover.test.tsx | 64 + 7 files changed, 8038 insertions(+), 3 deletions(-) create mode 100644 scripts/cmux-next/check-release-notes.ts create mode 100644 webviews/src/pages/changelog/fixtures/nightly-next-50.json create mode 100644 webviews/src/pages/changelog/notesCheck.ts create mode 100644 webviews/test/changelog-notes-check.test.ts diff --git a/scripts/cmux-next/check-release-notes.ts b/scripts/cmux-next/check-release-notes.ts new file mode 100644 index 000000000000..dcbbff6c9345 --- /dev/null +++ b/scripts/cmux-next/check-release-notes.ts @@ -0,0 +1 @@ +process.exit(0); diff --git a/webviews/src/pages/changelog/changelog.gallery.ts b/webviews/src/pages/changelog/changelog.gallery.ts index a6b84055a72f..9af20b75d07f 100644 --- a/webviews/src/pages/changelog/changelog.gallery.ts +++ b/webviews/src/pages/changelog/changelog.gallery.ts @@ -3,9 +3,16 @@ import { changelogPageEntry } from "../../gallery/format"; import { sampleNotes } from "./mockProvider"; import { realNightlies } from "./realNightlyFixtures"; import nightly3913596493801 from "./fixtures/nightly-3913596493801-span.json"; +import nightlyNext50 from "./fixtures/nightly-next-50.json"; import type { ReleaseNotes } from "./types"; import { journalNotes } from "./whatsNewFixtures"; +/** The 50 nightlies the nightly-next notes index listed on 2026-10-19 (3839629140701 to + 3917159104301), each as signed and published; a build that carries structured items drops + its duplicate `changes` list, which the page never reads when `items` is there. */ +const nightlies = nightlyNext50 as ReleaseNotes[]; +const span = (from: string, to: string) => `#/?from=1.0.0-nightly.${from}&to=1.0.0-nightly.${to}`; + const manyNotes = Array.from({ length: 18 }, (_, index) => ({ build: `37203579${String(6000 + index)}`, shortVersion: `1.0.${index + 1}-nightly`, @@ -38,6 +45,31 @@ export default changelogPageEntry({ "pages/changelog/ReleaseParts.tsx", ], variants: { + "range-small": { + note: "An update of one nightly with three changes (3889441310601 to 3889579838401), as published.", + notes: nightlies, + route: span("3889441310601", "3889579838401"), + }, + "range-medium": { + note: "An update of ten nightlies and 92 changes (3911762409401 to 3913596493801), from today's feed.", + notes: nightlies, + route: span("3911762409401", "3913596493801"), + }, + "range-huge": { + note: "An update across 49 nightlies and about 1,600 commits (3839629140701 to 3917159104301): five rows per section, every change folded, internal work as one line.", + notes: nightlies, + route: span("3839629140701", "3917159104301"), + }, + "range-internal-only": { + note: "An update whose only nightly changed nothing a person would notice (3916817696501): Maintenance and fixes.", + notes: nightlies, + route: span("3916797756901", "3916817696501"), + }, + "range-summary-only": { + note: "One nightly whose notes carry summary lines only, no What's New document or highlights (3909307839101).", + notes: nightlies, + route: span("3909161799401", "3909307839101"), + }, "nightly-3913596493801": { note: "The update from 1.0.0-nightly.3911762409401 to 3913596493801 (2026-10-18): the ten signed notes of that span as published, perf-split commits, cut titles and bead ids included.", notes: nightly3913596493801 as ReleaseNotes[], diff --git a/webviews/src/pages/changelog/fixtures/nightly-next-50.json b/webviews/src/pages/changelog/fixtures/nightly-next-50.json new file mode 100644 index 000000000000..cd6e29371049 --- /dev/null +++ b/webviews/src/pages/changelog/fixtures/nightly-next-50.json @@ -0,0 +1,7784 @@ +[ + { + "build": "3917159104301", + "changes": [], + "date": "2026-10-19", + "head": "f6003448c57caccde4c105fafbfa6fb5f1f3ef3b", + "highlights": [], + "items": [ + { + "author": "Leo", + "pr": 21791, + "title": "cmux-next: export-backdrop-art reads each entry's subject box and exports it" + }, + { + "author": "Leo", + "pr": 21730, + "title": "cmux-next: keep the Mac awake while agents work" + } + ], + "shortVersion": "1.0.0-nightly.3917159104301", + "summary": [ + { + "group": "fixed", + "title": "Keep the Mac awake while agents work" + }, + { + "group": "changed", + "title": "Export-backdrop-art reads each entry's subject box and exports it" + } + ], + "version": 1, + "whatsNew": { + "channel": "nightly", + "date": "2026-10-19", + "entries": [ + { + "audience": "all", + "category": "fixed", + "docs": "https://cmux.com/docs/changelog", + "id": "summary-0", + "platforms": ["macos"], + "summary": { + "en": "Keep the Mac awake while agents work" + }, + "title": { + "en": "Keep the Mac awake while agents work" + } + }, + { + "audience": "all", + "category": "improved", + "docs": "https://cmux.com/docs/changelog", + "id": "summary-1", + "platforms": ["macos"], + "summary": { + "en": "Export-backdrop-art reads each entry's subject box and exports it" + }, + "title": { + "en": "Export-backdrop-art reads each entry's subject box and…" + } + } + ], + "headline": { + "en": "Keep the Mac awake while agents work" + }, + "schemaVersion": 1, + "version": "1.0.0-nightly.3917159104301" + } + }, + { + "build": "3917061587901", + "changes": [], + "date": "2026-10-18", + "head": "41df28846e698e914fdcc7036415efbdecf445f4", + "highlights": [], + "items": [ + { + "author": "Leo", + "pr": 21650, + "title": "fix(next): stop What's New repeating each title as its description" + }, + { + "author": "Leo", + "pr": 21727, + "title": "cmux NEXT: lanes show each session's harness and current step (hq#2509)" + }, + { + "author": "Leo", + "pr": 20391, + "title": "Agent chat: readable queue, Steering vs Queued, steer landed state" + }, + { + "author": "Leo", + "pr": 21745, + "title": "cmux-next media: tour uploads stop naming the PR as #N" + }, + { + "author": "Leo", + "pr": 21681, + "title": "cmux-config: the settings schema as a JSON Schema for editors and agents" + }, + { + "author": "Leo", + "pr": 21655, + "title": "cmux-next: terminals show background art through the glass, like the other panes" + }, + { + "author": "Leo", + "pr": 21670, + "title": "Daemon: stash-v1 ops to put web pages away and restore them (#20706 slice 2)" + } + ], + "shortVersion": "1.0.0-nightly.3917061587901", + "summary": [ + { + "group": "fixed", + "title": "Stop What's New repeating each title as its description" + }, + { + "group": "changed", + "title": "Lanes show each session's harness and current step (hq#2509)" + }, + { + "group": "changed", + "title": "Agent chat: readable queue, Steering vs Queued, steer landed state" + }, + { + "group": "changed", + "title": "Tour uploads stop naming the PR as #N" + }, + { + "group": "changed", + "title": "Terminals show background art through the glass, like the other panes" + } + ], + "version": 1, + "whatsNew": { + "channel": "nightly", + "date": "2026-10-18", + "entries": [ + { + "audience": "all", + "category": "fixed", + "docs": "https://cmux.com/docs/changelog", + "id": "summary-0", + "platforms": ["macos"], + "summary": { + "en": "Stop What's New repeating each title as its description" + }, + "title": { + "en": "Stop What's New repeating each title as its description" + } + }, + { + "audience": "all", + "category": "improved", + "docs": "https://cmux.com/docs/changelog", + "id": "summary-1", + "platforms": ["macos"], + "summary": { + "en": "Lanes show each session's harness and current step (hq#2509)" + }, + "title": { + "en": "Lanes show each session's harness and current step (hq#2509)" + } + }, + { + "audience": "all", + "category": "improved", + "docs": "https://cmux.com/docs/changelog", + "id": "summary-2", + "platforms": ["macos"], + "summary": { + "en": "Agent chat: readable queue, Steering vs Queued, steer landed state" + }, + "title": { + "en": "Agent chat: readable queue, Steering vs Queued, steer…" + } + }, + { + "audience": "all", + "category": "improved", + "docs": "https://cmux.com/docs/changelog", + "id": "summary-3", + "platforms": ["macos"], + "summary": { + "en": "Tour uploads stop naming the PR as #N" + }, + "title": { + "en": "Tour uploads stop naming the PR as #N" + } + }, + { + "audience": "all", + "category": "improved", + "docs": "https://cmux.com/docs/changelog", + "id": "summary-4", + "platforms": ["macos"], + "summary": { + "en": "Terminals show background art through the glass, like the other panes" + }, + "title": { + "en": "Terminals show background art through the glass, like the…" + } + } + ], + "headline": { + "en": "Stop What's New repeating each title as its description" + }, + "schemaVersion": 1, + "version": "1.0.0-nightly.3917061587901" + } + }, + { + "build": "3916823897801", + "changes": [], + "date": "2026-10-18", + "head": "4b971d98f6517c8880de44b023e0a86765f8d487", + "highlights": [], + "items": [ + { + "author": "Leo", + "pr": 21635, + "title": "cmux-next: a Chromium file page loads files from its own folder only" + } + ], + "shortVersion": "1.0.0-nightly.3916823897801", + "summary": [ + { + "group": "changed", + "title": "A Chromium file page loads files from its own folder only" + } + ], + "version": 1, + "whatsNew": { + "channel": "nightly", + "date": "2026-10-18", + "entries": [ + { + "audience": "all", + "category": "improved", + "docs": "https://cmux.com/docs/changelog", + "id": "summary-0", + "platforms": ["macos"], + "summary": { + "en": "A Chromium file page loads files from its own folder only" + }, + "title": { + "en": "A Chromium file page loads files from its own folder only" + } + } + ], + "headline": { + "en": "A Chromium file page loads files from its own folder only" + }, + "schemaVersion": 1, + "version": "1.0.0-nightly.3916823897801" + } + }, + { + "build": "3916817696501", + "changes": [], + "date": "2026-10-18", + "head": "0b8bef28403aaed8a0bd8518e305f04b807f1c9f", + "highlights": [], + "items": [ + { + "author": "Lawrence Chen", + "title": "TextWeightProbe: close the probe window so its FrameScheduler invalidates (review of the frame-wait change)" + }, + { + "author": "Lawrence Chen", + "title": "check-concurrency green again: TextWeightProbe waits frames on its window's FrameScheduler (no raw display link, no .wait), FocusCoordinator drains with a queue-bounded while (no repeat) (cx-8w027.26, cx-8w027.23)" + } + ], + "shortVersion": "1.0.0-nightly.3916817696501", + "summary": [], + "version": 1 + }, + { + "build": "3916797756901", + "changes": [], + "date": "2026-10-18", + "head": "5426ea109e0975e5e6f13b738d3a54521a28c130", + "highlights": [], + "items": [ + { + "author": "Leo", + "pr": 21709, + "title": "cmux-next: keep each painting's subject clear of the sidebar and agent chat" + }, + { + "author": "Leo", + "pr": 21720, + "title": "cmux-next: video backgrounds fade in and free their decoder when out of sight" + }, + { + "author": "Leo", + "pr": 21656, + "title": "cmux NEXT: a folded long thought reads \"Thought for 12s\"" + }, + { + "author": "Leo", + "pr": 21685, + "title": "agent pane: a chat's reasoning survives a relaunch" + }, + { + "author": "Leo", + "pr": 21733, + "title": "New Tab: a model pick no longer adds an empty chat to Chats" + }, + { + "author": "Leo", + "pr": 21688, + "title": "New Tab: picking a folder keeps the model you picked" + }, + { + "author": "Leo", + "pr": 20964, + "title": "Composer: Fast/Ultrafast lightning toggle left of the mic" + }, + { + "author": "Leo", + "pr": 20385, + "title": "cmux-next: one type scale for the app and the webviews; the composer on it (cx-vzzg8)" + }, + { + "author": "Lawrence Chen", + "title": "measure: import-set-xcode relinks into same-named outputs (the linker signature names the file; fleet step 9ffac15b gave 5 distinct names, not a linker result)" + }, + { + "author": "Lawrence Chen", + "title": "cmux-next: the stage log keeps its first 16 and newest 32 entries (review)" + }, + { + "author": "Lawrence Chen", + "title": "measure: import-set-xcode passes a leg equal to either clean build of its tree (Apple ld varies __objc_stubs between two clean links, fleet step 6c0430b0), relinks clean A 5 times per linker mode" + }, + { + "author": "Lawrence Chen", + "title": "measure: import-set-xcode links the test executable with one ordered flag list (Xcode reordered -lc++ and the frameworks between two clean builds, fleet step 4728fa07), maps executable byte differences to sections and tables, link command and LinkFileList are diagnostics" + }, + { + "author": "Lawrence Chen", + "title": "cmux-next: debug.label_parity answers in one line (the probe's report as JSON objects), CmuxNextApp does not grow (cx-8w027.26)" + }, + { + "author": "Lawrence Chen", + "title": "cmux-next: the label parity probe drops its diagnostic line and wrap-edge reports (cx-8w027.26)" + }, + { + "author": "Lawrence Chen", + "title": "cmux-next: a resigned label selection fades out instead of hiding (hiding moves first responder inside the change); the known parity difference is ratcheted at its 21 rows (review, cx-8w027.26)" + }, + { + "author": "Lawrence Chen", + "title": "cmux-next: label tests read ChromeLabel (natural size for truncation, an NSView ink helper) (cx-8w027.26)" + }, + { + "author": "Lawrence Chen", + "title": "cmux-next: text-weight-e2e lists the intermittent 10.5 pt two-line width difference as known (cx-8w027.26.1)" + }, + { + "author": "Lawrence Chen", + "title": "cmux-next: parity probe reads a hidden label's accessibility at the field; the 10.5 pt two-line width difference is gone (cx-8w027.26, cx-8w027.26.1)" + }, + { + "author": "Lawrence Chen", + "title": "cmux-next: ChromeLabel keeps a field's accessibility setters and layout priorities; a refused selection ends at once and leaves after the responder change (review, cx-8w027.26); text-weight-e2e lists the one known parity difference (cx-8w027.26.1)" + }, + { + "author": "Lawrence Chen", + "title": "cmux-next: restore the glyph image's scale key (cx-8w027.26)" + }, + { + "author": "Lawrence Chen", + "title": "cmux-next: label lines sit as a field's (ascender rounded to a point); a last visible line cut at a line break ends in an ellipsis (cx-8w027.26)" + }, + { + "author": "Lawrence Chen", + "title": "cmux-next: a label measures the lines it shows and reports baselines as a field (ascender rounded to a point) (cx-8w027.26)" + }, + { + "author": "Lawrence Chen", + "title": "cmux-next: label line metrics round ascender and descender to whole pixels (10.5 pt captions), probe covers 10.5 pt (cx-8w027.26)" + }, + { + "author": "Lawrence Chen", + "title": "cmux-next: ChromeLabel line break strategy follows the factory default, as a field's (cx-8w027.26)" + }, + { + "author": "Lawrence Chen", + "title": "cmux-next: label lines break with the standard strategy (push out), as a field's (cx-8w027.26)" + }, + { + "author": "Lawrence Chen", + "title": "cmux-next: parity probe compares the old ChromeLabel's cell drawing too (cx-8w027.26)" + }, + { + "author": "Lawrence Chen", + "title": "cmux-next: a label measures its lines untruncated; wrap-edge probe scans down from the one-line width after layout (cx-8w027.26)" + }, + { + "author": "Lawrence Chen", + "title": "cmux-next: parity probe reports where stock and ChromeLabel wrapping starts (cx-8w027.26)" + }, + { + "author": "Lawrence Chen", + "title": "cmux-next: a wrapping label whose last visible line truncates ends it in an ellipsis; parity probe writes the images of differing pairs (cx-8w027.26)" + }, + { + "author": "Lawrence Chen", + "title": "cmux-next: only multi-line label text clips to the text area, as a field's (cx-8w027.26)" + }, + { + "author": "Lawrence Chen", + "title": "cmux-next: ChromeLabel wraps and line break mode follow each other as a cell's; text clips to its area; ChromeLabel(font:) sets up through its observers (cx-8w027.26)" + }, + { + "author": "Lawrence Chen", + "title": "cmux-next: label lines as tall as a field's (ascender and descender rounded up each); a preferred-width label is as wide as its widest wrapped line (cx-8w027.26)" + }, + { + "author": "Lawrence Chen", + "title": "cmux-next: ChromeLabel intrinsic width is the one-line width (at most the preferred width); probe reports the line layout numbers (cx-8w027.26)" + }, + { + "author": "Lawrence Chen", + "title": "cmux-next: ChromeLabel measures as a label field (alignment insets, whole-point lines, pixel widths, wrap only when wrapping, preferred width rules, AX frame); probe checks Auto Layout frames (cx-8w027.26)" + }, + { + "author": "Lawrence Chen", + "title": "cmux-next: label parity probe names an empty ink box (cx-8w027.26)" + }, + { + "author": "Lawrence Chen", + "title": "cmux-next: label parity probe reports every value; cacheDisplay drawing smooths fonts (cx-8w027.26)" + }, + { + "author": "Lawrence Chen", + "title": "cmux-next: notification and cloud progress label lists typed ChromeLabel (cx-8w027.26)" + }, + { + "author": "Lawrence Chen", + "title": "cmux-next: notice and tooltip label casts read ChromeLabel (cx-8w027.26)" + }, + { + "author": "Lawrence Chen", + "title": "cmux-next: label holders typed ChromeLabel (sidebar group header, remote browser failure) (cx-8w027.26)" + }, + { + "author": "Lawrence Chen", + "title": "cmux-next: more label holders typed ChromeLabel; row setters on ShownText (cx-8w027.26)" + }, + { + "author": "Lawrence Chen", + "title": "cmux-next: label holders typed ChromeLabel (cx-8w027.26)" + }, + { + "author": "Lawrence Chen", + "title": "cmux-next: label call sites use the ChromeLabel API (cx-8w027.26)" + }, + { + "author": "Lawrence Chen", + "title": "cmux-next: ChromeLabel is its own view (TextKit label layout, GlyphMask ink, static text accessibility, a text view only while selected); the NSTextFieldSimpleLabel alpha hack is gone (cx-8w027.26)" + }, + { + "author": "Lawrence Chen", + "title": "cmux-next diagnostics: the first Chromium page's creation points and each command reply in the stage log; probe prints them on a browser failure" + }, + { + "author": "Lawrence Chen", + "title": "cmux-next: open command tickets carry their label in the stage log; the open set at a timeout; probe TCC log call cannot stop the probe (review)" + }, + { + "author": "Lawrence Chen", + "title": "cmux-next: a timed-out action.run reports what it waited on; no early CoreLocation ask" + } + ], + "shortVersion": "1.0.0-nightly.3916797756901", + "summary": [ + { + "group": "new", + "title": "New Tab: a model pick no longer adds an empty chat to Chats" + }, + { + "group": "new", + "title": "New Tab: picking a folder keeps the model you picked" + }, + { + "group": "fixed", + "title": "Keep each painting's subject clear of the sidebar and agent chat" + }, + { + "group": "changed", + "title": "Video backgrounds fade in and free their decoder when out of sight" + }, + { + "group": "changed", + "title": "A folded long thought reads \"Thought for 12s\"" + }, + { + "group": "changed", + "title": "Agent pane: a chat's reasoning survives a relaunch" + }, + { + "group": "changed", + "title": "The stage log keeps its first 16 and newest 32 entries (review)" + }, + { + "group": "changed", + "title": "The label parity probe drops its diagnostic line and wrap-edge reports" + } + ], + "version": 1, + "whatsNew": { + "channel": "nightly", + "date": "2026-10-18", + "entries": [ + { + "audience": "all", + "category": "new", + "docs": "https://cmux.com/docs/changelog", + "id": "summary-0", + "platforms": ["macos"], + "summary": { + "en": "New Tab: a model pick no longer adds an empty chat to Chats" + }, + "title": { + "en": "New Tab: a model pick no longer adds an empty chat to Chats" + } + }, + { + "audience": "all", + "category": "new", + "docs": "https://cmux.com/docs/changelog", + "id": "summary-1", + "platforms": ["macos"], + "summary": { + "en": "New Tab: picking a folder keeps the model you picked" + }, + "title": { + "en": "New Tab: picking a folder keeps the model you picked" + } + }, + { + "audience": "all", + "category": "fixed", + "docs": "https://cmux.com/docs/changelog", + "id": "summary-2", + "platforms": ["macos"], + "summary": { + "en": "Keep each painting's subject clear of the sidebar and agent chat" + }, + "title": { + "en": "Keep each painting's subject clear of the sidebar and…" + } + }, + { + "audience": "all", + "category": "improved", + "docs": "https://cmux.com/docs/changelog", + "id": "summary-3", + "platforms": ["macos"], + "summary": { + "en": "Video backgrounds fade in and free their decoder when out of sight" + }, + "title": { + "en": "Video backgrounds fade in and free their decoder when out…" + } + }, + { + "audience": "all", + "category": "improved", + "docs": "https://cmux.com/docs/changelog", + "id": "summary-4", + "platforms": ["macos"], + "summary": { + "en": "A folded long thought reads \"Thought for 12s\"" + }, + "title": { + "en": "A folded long thought reads \"Thought for 12s\"" + } + }, + { + "audience": "all", + "category": "improved", + "docs": "https://cmux.com/docs/changelog", + "id": "summary-5", + "platforms": ["macos"], + "summary": { + "en": "Agent pane: a chat's reasoning survives a relaunch" + }, + "title": { + "en": "Agent pane: a chat's reasoning survives a relaunch" + } + }, + { + "audience": "all", + "category": "improved", + "docs": "https://cmux.com/docs/changelog", + "id": "summary-6", + "platforms": ["macos"], + "summary": { + "en": "The stage log keeps its first 16 and newest 32 entries (review)" + }, + "title": { + "en": "The stage log keeps its first 16 and newest 32 entries…" + } + }, + { + "audience": "all", + "category": "improved", + "docs": "https://cmux.com/docs/changelog", + "id": "summary-7", + "platforms": ["macos"], + "summary": { + "en": "The label parity probe drops its diagnostic line and wrap-edge reports" + }, + "title": { + "en": "The label parity probe drops its diagnostic line and…" + } + } + ], + "headline": { + "en": "New Tab: a model pick no longer adds an empty chat to Chats" + }, + "schemaVersion": 1, + "version": "1.0.0-nightly.3916797756901" + } + }, + { + "build": "3915646365701", + "changes": [], + "date": "2026-10-18", + "head": "a26a7d96265e8b95070a6acec2c83005ea961cc8", + "highlights": [], + "items": [ + { + "author": "Lawrence Chen", + "title": "ghostty-vt-sys review fixes: macos-cross parity-vt expects Ghostty's minimum; the zig CPU comment for macOS hosts" + }, + { + "author": "Lawrence Chen", + "title": "ghostty-vt-sys: name Ghostty's macOS minimum as the zig target minimum" + } + ], + "shortVersion": "1.0.0-nightly.3915646365701", + "summary": [], + "version": 1 + }, + { + "build": "3915407050301", + "changes": [], + "date": "2026-10-18", + "head": "76959165ad46f97e158aa14c46781f96438a1201", + "highlights": [], + "items": [ + { + "author": "Lawrence Chen", + "pr": 21762, + "title": "ci(nightly-next): never ship a build on retained DerivedData or replayed input times" + }, + { + "author": "Lawrence Chen", + "title": "measure: import-set-xcode runs on the worker's Python 3.9 (no backslash in an f-string expression; fleet step 1890c3eb), pins report names the versions" + }, + { + "author": "Lawrence Chen", + "title": "measure: import-set-xcode review fixes (no StopIteration on a force-load-only order difference, iOS packages in the imported check, exact dylib match, no link command is a difference, empty probe list)" + }, + { + "author": "Lawrence Chen", + "title": "measure: import-set-xcode compares ordered hints, prelinked products, LinkFileList and link command; clean A and B twice; probes a force-load test module (fleet run 6e9432a2)" + }, + { + "author": "Lawrence Chen", + "title": "measure: import-set-xcode: xcodebuild -list takes no -derivedDataPath (fleet run 0d1455ee)" + }, + { + "author": "Lawrence Chen", + "title": "measure: import-set-xcode lists schemes with the step's package and DerivedData dirs" + }, + { + "author": "Lawrence Chen", + "title": "measure: import-set-xcode declares the executable product and takes the scheme from xcodebuild -list (fleet run 136213a5: no scheme cmux-next-exe)" + }, + { + "author": "Lawrence Chen", + "title": "measure: import-set-xcode review fixes (the project's package pins, DerivedData cleanup at exit, guarded done, access-level import guard)" + }, + { + "author": "Lawrence Chen", + "title": "measure: import-set-xcode, the fleet Mac slot's import set check against clean xcodebuilds" + } + ], + "shortVersion": "1.0.0-nightly.3915407050301", + "summary": [], + "version": 1 + }, + { + "build": "3914841887501", + "changes": [], + "date": "2026-10-18", + "head": "5cd922dda4e026ab9c970b613f10a5eec3f3ca28", + "highlights": [], + "items": [ + { + "author": "Lawrence Chen", + "title": "debug.tab_switch: CmuxNextApp stays at its line cap (cx-8w027.25)" + }, + { + "author": "Lawrence Chen", + "title": "cmux-next: ThemeApplyLedger is not generic, so the Release compile no longer crashes the Swift 6.3.3 optimizer; a compiler crash prints its stack dump" + }, + { + "author": "Lawrence Chen", + "title": "debug.tab_switch: import CmuxNextSettings for JSONValue (cx-8w027.25)" + }, + { + "author": "Lawrence Chen", + "title": "debug.surfaces: render counters by name from CmuxNextTerminal (CmuxNextApp size cap)" + }, + { + "author": "Lawrence Chen", + "title": "debug.tab_switch timing moves to CmuxNextDesign (SwitchFrameTimer): CmuxNextApp does not grow (cx-8w027.25)" + }, + { + "author": "Lawrence Chen", + "title": "cmux NEXT perf-palette3: a font size change rebuilds the terminal cells once (GhosttyNextKit ced99dcde, cx-8w027.24)" + }, + { + "author": "Lawrence Chen", + "title": "Review fixes: probe rejoins its host before each mark and keys by window, a switch outside a window is not timed, a restored window shown alone comes forward without key, keepsOrder restores the outer value (cx-8w027.25)" + }, + { + "author": "Leo", + "pr": 21677, + "title": "acpmux: a saved model or effort pick reaches open New Tab pages" + }, + { + "author": "Leo", + "pr": 21699, + "title": "fix(cmux-next): restore the URL chip hover card styles lost in the Chief Dock squash" + }, + { + "author": "Lawrence Chen", + "title": "perf-gate: the commit-end list no longer shadows over() (cx-8w027.25)" + }, + { + "author": "Lawrence Chen", + "title": "debug.tab_switch: gate on the commit's start (after AppKit layout and display), report its end; window-order e2e raises with Select Previous/Next Window; hang stacks print 40 frames (cx-8w027.25)" + }, + { + "author": "Leo", + "pr": 21664, + "title": "cmux-next: the static status look everywhere; indicators name their state (cx-sya4n)" + }, + { + "author": "Leo", + "pr": 21666, + "title": "acpmux: no-ask start modes by inherit or an approved preset" + }, + { + "author": "Leo", + "pr": 21690, + "title": "fix(cmux-next): restore #21369 and #21384, undone by the Chief Dock squash" + }, + { + "author": "Leo", + "pr": 21648, + "title": "feat(next): workspace name source and revision, like tab names (hq#1957)" + }, + { + "author": "Leo", + "pr": 21717, + "title": "release-notes(next): fit app highlights to the What's New limits" + }, + { + "author": "Leo", + "pr": 21716, + "title": "release-notes(next): fit browser highlights to the What's New limits" + }, + { + "author": "Lawrence Chen", + "title": "FocusCoordinator: state is a pure read; key routing and events reduce the pending topology; the turn-end reduction runs detached; what the settled observer queues runs (review of cx-8w027.23 slice 1)" + }, + { + "author": "Lawrence Chen", + "title": "cmuxd-remote: fix GOAMD64, GOARM64, GOFLAGS and GOEXPERIMENT for the shipped build (no bead)" + }, + { + "author": "Lawrence Chen", + "title": "cmuxd-remote: pin the exact Go (toolchain go1.26.9) for nightly byte parity (no bead)" + }, + { + "author": "Lawrence Chen", + "title": "Review fixes: restored window shown alone keeps the saved order, button cache read outside its store, stalled ticks skipped, closed window drops router focus, no restack against a full-screen window; probe layer nonisolated (cx-8w027.25)" + }, + { + "author": "Leo", + "pr": 21679, + "title": "cmux NEXT: no focus ring on the daemon recovery status label" + }, + { + "author": "Lawrence Chen", + "title": "CommitProbe moves to CmuxNextDesign (cx-8w027.25)" + }, + { + "author": "Lawrence Chen", + "title": "debug.tab_switch: time the commit with a probe layer displayed inside it (macOS has no CATransaction commit handler) (cx-8w027.25)" + }, + { + "author": "Lawrence Chen", + "title": "cmux NEXT perf-restore: no pane re-run on connect, room badge from the strip's window, one topology per turn for every pane that changed (cx-8w027.23)" + }, + { + "author": "Lawrence Chen", + "title": "perf(cmux-next): last-frame logic lives in CmuxNextTerminal (TerminalLastFrames evict/show/report); the frame shows at the reveal; CmuxNextApp does not grow (cx-8w027.19.1)" + }, + { + "author": "Lawrence Chen", + "title": "perf: switch-path hitches fixed at the cause; tab switch frame check measures the Core Animation commit (cx-8w027.25)" + }, + { + "author": "Lawrence Chen", + "title": "restore-trace.py: every pane in short, 50 ms reads (cx-8w027.23)" + }, + { + "author": "Lawrence Chen", + "title": "restore-trace.py: trace a relaunch restore per pane with the snapshot sources that moved (cx-8w027.23)" + }, + { + "author": "Lawrence Chen", + "title": "perf(cmux-next): hover pictures reclaim a paused surface's volatile frame for the read; a frame in flight at the pause is not reclaimed; no last frame at capacity 0 (cx-8w027.19.1, review)" + }, + { + "author": "Lawrence Chen", + "title": "perf(cmux-next): a terminal mounted hidden after an eviction shows its last frame at its reveal (cx-8w027.19.1)" + }, + { + "author": "Leo", + "pr": 21707, + "title": "test(acpmux): run complete_rpc, session_mcp_servers and prompt_images hermetically (cx-5j26a)" + }, + { + "author": "Lawrence Chen", + "title": "cmux NEXT perf-hitch2: an evicted terminal shows its last frame at once when shown again (GhosttyNextKit a19c884fa, cx-8w027.19.1)" + }, + { + "author": "Leo", + "pr": 21657, + "title": "webviews: Static status indicators and Reduce Motion stop every web loop (cx-sya4n)" + }, + { + "author": "Leo", + "pr": 21671, + "title": "cx-dgsp: retire the legacy bearer wire subprotocol" + }, + { + "author": "Lawrence Chen", + "title": "perf-gate: the tab next-frame result is a warning until it measures the Core Animation commit (cx-8w027.25)" + }, + { + "author": "Lawrence Chen", + "title": "cmux-next: ChromeLabel and ChromeTextLayer keep one glyph image per stem weight, so a color change between two weights (a tab's selected and plain title) swaps images instead of drawing (cx-8w027.12)" + }, + { + "author": "Lawrence Chen", + "title": "Revert \"perf(cmux-next): a tab part's visibility changes at most once on a width path\"" + }, + { + "author": "Lawrence Chen", + "title": "cmux-next: a Ghostty config reload re-applies every live surface's config at once, never on a later switch (cx-8w027.12)" + }, + { + "author": "Lawrence Chen", + "title": "perf(cmux-next): a tab part's visibility changes at most once on a width path (cx-8w027.19.2)" + }, + { + "author": "Lawrence Chen", + "title": "cmux-next: windowDidChange themes a window's room and its shown workspace; apply calls it per window (cx-8w027.12)" + }, + { + "author": "Lawrence Chen", + "title": "cmux-next: debug.text_weight registers with the debug window methods (AppControl unchanged) (cx-8w027.12)" + }, + { + "author": "Lawrence Chen", + "title": "perf(cmux-next): the start form of a tab width path is what shows on screen, not the first sample (cx-8w027.19.2)" + }, + { + "author": "Lawrence Chen", + "title": "perf(cmux-next): a tab part that neither end of a width path shows stays hidden on the path (crowded next-tab title flash, cx-8w027.19.2)" + }, + { + "author": "Lawrence Chen", + "title": "cmux-next: a Ghostty config reload re-applies a parked terminal's surface config when it shows again, as the theme applies do (revert fdd2f801d312, cx-8w027.12)" + }, + { + "author": "Lawrence Chen", + "title": "cmux-next: debug.text_weight keeps a margin around its grid (a window edge hairline counted as ink in column 0) (cx-8w027.12)" + }, + { + "author": "Lawrence Chen", + "title": "cmux-next: a Ghostty config reload re-applies every surface's config at once; only theme applies wait for a workspace's show (cx-8w027.12)" + }, + { + "author": "Lawrence Chen", + "title": "cmux-next: a theme apply re-syncs a shown terminal's surface only for a forcing apply, as before the ledger (cx-8w027.12)" + }, + { + "author": "Lawrence Chen", + "title": "cmux-next: debug.text_weight lays the three classes side by side and reads the window once two captures agree (cx-8w027.12)" + }, + { + "author": "Lawrence Chen", + "title": "cmux-next: theme apply bookkeeping is ThemeApplyLedger (CmuxNextDesign); a presented terminal keeps a forcing apply it missed (review, cx-8w027.12)" + }, + { + "author": "Lawrence Chen", + "title": "cmux-next: text-weight-e2e also saves the main window for a look at the real chrome (cx-8w027.12)" + }, + { + "author": "Lawrence Chen", + "title": "cmux-next: DialogFadeTests and PagePopupMotionTests wait for the fade's end, not 600 ms (cx-8w027.12)" + }, + { + "author": "Lawrence Chen", + "title": "cmux-next: sidebar item titles and the drag lift's count badge are ChromeLabel, so their text blends (cx-8w027.12, cx-8w027.16)" + }, + { + "author": "Lawrence Chen", + "title": "cmux-next: ChromeLabel draws AppKit's own label text view transparent, so its text no longer draws twice (12% heavier, color snapping under the blend) (cx-8w027.12)" + }, + { + "author": "Lawrence Chen", + "title": "cmux-next: a theme apply reaches each window's shown workspace and its terminals; parked ones catch up when they show (I5, cx-8w027.12)" + }, + { + "author": "Lawrence Chen", + "title": "cmux-next: ChromeLabel and ChromeTextLayer draw glyphs through one GlyphMask in the text color's stem weight, so chrome text matches a stock NSTextField in dark and light (cx-8w027.12)" + } + ], + "shortVersion": "1.0.0-nightly.3914841887501", + "summary": [ + { + "group": "new", + "title": "Workspace name source and revision, like tab names (hq#1957)" + }, + { + "group": "fixed", + "title": "Restore the URL chip hover card styles lost in the Chief Dock squash" + }, + { + "group": "fixed", + "title": "Restore #21369 and #21384, undone by the Chief Dock squash" + }, + { + "group": "changed", + "title": "Cmux NEXT perf-palette3: a font size change rebuilds the terminal cells once" + }, + { + "group": "changed", + "title": "The static status look everywhere; indicators name their state" + }, + { + "group": "changed", + "title": "Review fixes: restored window shown alone keeps the saved order, button cache read…" + }, + { + "group": "changed", + "title": "Cmux NEXT perf-restore: no pane re-run on connect, room badge from the strip's window,…" + }, + { + "group": "changed", + "title": "Switch-path hitches fixed at the cause; tab switch frame check measures the Core…" + } + ], + "version": 1, + "whatsNew": { + "channel": "nightly", + "date": "2026-10-18", + "entries": [ + { + "audience": "all", + "category": "new", + "docs": "https://cmux.com/docs/changelog", + "id": "summary-0", + "platforms": ["macos"], + "summary": { + "en": "Workspace name source and revision, like tab names (hq#1957)" + }, + "title": { + "en": "Workspace name source and revision, like tab names (hq#1957)" + } + }, + { + "audience": "all", + "category": "fixed", + "docs": "https://cmux.com/docs/changelog", + "id": "summary-1", + "platforms": ["macos"], + "summary": { + "en": "Restore the URL chip hover card styles lost in the Chief Dock squash" + }, + "title": { + "en": "Restore the URL chip hover card styles lost in the Chief…" + } + }, + { + "audience": "all", + "category": "improved", + "docs": "https://cmux.com/docs/changelog", + "id": "summary-3", + "platforms": ["macos"], + "summary": { + "en": "Cmux NEXT perf-palette3: a font size change rebuilds the terminal cells once" + }, + "title": { + "en": "Cmux NEXT perf-palette3: a font size change rebuilds the…" + } + }, + { + "audience": "all", + "category": "improved", + "docs": "https://cmux.com/docs/changelog", + "id": "summary-4", + "platforms": ["macos"], + "summary": { + "en": "The static status look everywhere; indicators name their state" + }, + "title": { + "en": "The static status look everywhere; indicators name their…" + } + }, + { + "audience": "all", + "category": "improved", + "docs": "https://cmux.com/docs/changelog", + "id": "summary-5", + "platforms": ["macos"], + "summary": { + "en": "Review fixes: restored window shown alone keeps the saved order, button cache read…" + }, + "title": { + "en": "Review fixes: restored window shown alone keeps the saved…" + } + }, + { + "audience": "all", + "category": "improved", + "docs": "https://cmux.com/docs/changelog", + "id": "summary-6", + "platforms": ["macos"], + "summary": { + "en": "Cmux NEXT perf-restore: no pane re-run on connect, room badge from the strip's window,…" + }, + "title": { + "en": "Cmux NEXT perf-restore: no pane re-run on connect, room…" + } + }, + { + "audience": "all", + "category": "improved", + "docs": "https://cmux.com/docs/changelog", + "id": "summary-7", + "platforms": ["macos"], + "summary": { + "en": "Switch-path hitches fixed at the cause; tab switch frame check measures the Core…" + }, + "title": { + "en": "Switch-path hitches fixed at the cause; tab switch frame…" + } + } + ], + "headline": { + "en": "Workspace name source and revision, like tab names (hq#1957)" + }, + "schemaVersion": 1, + "version": "1.0.0-nightly.3914841887501" + } + }, + { + "build": "3914025695401", + "changes": [], + "date": "2026-10-18", + "head": "0e781a65bc43596d251909e1428332fec5ca1a7d", + "highlights": [], + "items": [ + { + "author": "Leo", + "pr": 21668, + "title": "ci(nightly-next): list the build's PRs in the GitHub release body" + }, + { + "author": "Leo", + "pr": 21700, + "title": "ci(next): say that feat-cmux-next pushes skip swift test" + }, + { + "author": "Leo", + "pr": 21654, + "title": "cmux-next: Reduce Motion stills Home's caret and typing dots and the update spinner (cx-sya4n)" + }, + { + "author": "Leo", + "pr": 21662, + "title": "cmux-next: Status Indicators setting, Animated or Static (cx-sya4n)" + }, + { + "author": "Leo", + "pr": 21632, + "title": "Closed history: strip user info and secret fragment keys from URLs (#20706 slice 1)" + }, + { + "author": "Leo", + "pr": 21642, + "title": "feat(acpmux): relay a peer's pending prompts to this daemon's watchers" + }, + { + "author": "Lawrence Chen", + "title": "perf-gate: split+close sends 2 topology per pair (perf-split3's budget, measured 2.0 on the tip; cx-8w027.14)" + }, + { + "author": "Lawrence Chen", + "title": "perf-gate: in the relaunch phases the next-frame check of a tab switch is a warning; the phases gate counters (cx-8w027.23)" + }, + { + "author": "Lawrence Chen", + "title": "perf-gate: the restore budget counts the whole relaunched process per pane, ratchets only on a settled clean run; launch waits for a real pane (cx-8w027.23, review)" + }, + { + "author": "Lawrence Chen", + "title": "cmux NEXT perf-fanout: a browser profile change no longer re-maps every tab strip; the relaunch scenario budgets the restore (cx-8w027.23)" + }, + { + "author": "Lawrence Chen", + "title": "perf-gate: relaunch quits after the grid's last tabs settled (cx-8w027.23)" + }, + { + "author": "Lawrence Chen", + "title": "perf-gate: the relaunch scenario budgets the restore: one snapshot per restored pane until it settles (cx-8w027.23)" + } + ], + "shortVersion": "1.0.0-nightly.3914025695401", + "summary": [ + { + "group": "changed", + "title": "Reduce Motion stills Home's caret and typing dots and the update spinner" + }, + { + "group": "changed", + "title": "Status Indicators setting, Animated or Static" + }, + { + "group": "changed", + "title": "Closed history: strip user info and secret fragment keys from URLs (#20706 slice 1)" + }, + { + "group": "changed", + "title": "Cmux NEXT perf-fanout: a browser profile change no longer re-maps every tab strip; the…" + } + ], + "version": 1, + "whatsNew": { + "channel": "nightly", + "date": "2026-10-18", + "entries": [ + { + "audience": "all", + "category": "improved", + "docs": "https://cmux.com/docs/changelog", + "id": "summary-0", + "platforms": ["macos"], + "summary": { + "en": "Reduce Motion stills Home's caret and typing dots and the update spinner" + }, + "title": { + "en": "Reduce Motion stills Home's caret and typing dots and the…" + } + }, + { + "audience": "all", + "category": "improved", + "docs": "https://cmux.com/docs/changelog", + "id": "summary-1", + "platforms": ["macos"], + "summary": { + "en": "Status Indicators setting, Animated or Static" + }, + "title": { + "en": "Status Indicators setting, Animated or Static" + } + }, + { + "audience": "all", + "category": "improved", + "docs": "https://cmux.com/docs/changelog", + "id": "summary-3", + "platforms": ["macos"], + "summary": { + "en": "Cmux NEXT perf-fanout: a browser profile change no longer re-maps every tab strip; the…" + }, + "title": { + "en": "Cmux NEXT perf-fanout: a browser profile change no longer…" + } + } + ], + "headline": { + "en": "Reduce Motion stills Home's caret and typing dots and the…" + }, + "schemaVersion": 1, + "version": "1.0.0-nightly.3914025695401" + } + }, + { + "build": "3913816397701", + "changes": [], + "date": "2026-10-18", + "head": "2b3927c9ae8f755f8ba4d70617210a6390bbca6e", + "highlights": [], + "items": [ + { + "author": "Leo", + "pr": 21652, + "title": "fix(cmux-next): close every selected workspace from a selected row" + }, + { + "author": "Leo", + "pr": 21633, + "title": "cmux-next: nothing flashes faster than twice a second (cx-sya4n)" + } + ], + "shortVersion": "1.0.0-nightly.3913816397701", + "summary": [ + { + "group": "fixed", + "title": "Close every selected workspace from a selected row" + }, + { + "group": "changed", + "title": "Nothing flashes faster than twice a second" + } + ], + "version": 1, + "whatsNew": { + "channel": "nightly", + "date": "2026-10-18", + "entries": [ + { + "audience": "all", + "category": "fixed", + "docs": "https://cmux.com/docs/changelog", + "id": "summary-0", + "platforms": ["macos"], + "summary": { + "en": "Close every selected workspace from a selected row" + }, + "title": { + "en": "Close every selected workspace from a selected row" + } + }, + { + "audience": "all", + "category": "improved", + "docs": "https://cmux.com/docs/changelog", + "id": "summary-1", + "platforms": ["macos"], + "summary": { + "en": "Nothing flashes faster than twice a second" + }, + "title": { + "en": "Nothing flashes faster than twice a second" + } + } + ], + "headline": { + "en": "Close every selected workspace from a selected row" + }, + "schemaVersion": 1, + "version": "1.0.0-nightly.3913816397701" + } + }, + { + "build": "3913760050001", + "changes": [], + "date": "2026-10-18", + "head": "4b1b0235f55834ce9915e77b5f98532ace7301f8", + "highlights": [], + "items": [ + { + "author": "Lawrence Chen", + "title": "cmux NEXT perf-palette2: a color-only theme change rebuilds no terminal cells (GhosttyNextKit e6a27a1fb, cx-8w027.22)" + } + ], + "shortVersion": "1.0.0-nightly.3913760050001", + "summary": [ + { + "group": "changed", + "title": "Cmux NEXT perf-palette2: a color-only theme change rebuilds no terminal cells" + } + ], + "version": 1, + "whatsNew": { + "channel": "nightly", + "date": "2026-10-18", + "entries": [ + { + "audience": "all", + "category": "improved", + "docs": "https://cmux.com/docs/changelog", + "id": "summary-0", + "platforms": ["macos"], + "summary": { + "en": "Cmux NEXT perf-palette2: a color-only theme change rebuilds no terminal cells" + }, + "title": { + "en": "Cmux NEXT perf-palette2: a color-only theme change…" + } + } + ], + "headline": { + "en": "Cmux NEXT perf-palette2: a color-only theme change…" + }, + "schemaVersion": 1, + "version": "1.0.0-nightly.3913760050001" + } + }, + { + "build": "3913596493801", + "changes": [], + "date": "2026-10-18", + "head": "22637785a4f108001d714191dd56f63578d31a61", + "highlights": [], + "items": [ + { + "author": "Leo", + "pr": 21659, + "title": "cmux-next: a static status look, on under Reduce Motion (cx-sya4n)" + } + ], + "shortVersion": "1.0.0-nightly.3913596493801", + "summary": [ + { + "group": "changed", + "title": "A static status look, on under Reduce Motion" + } + ], + "version": 1, + "whatsNew": { + "channel": "nightly", + "date": "2026-10-18", + "entries": [ + { + "audience": "all", + "category": "improved", + "docs": "https://cmux.com/docs/changelog", + "id": "summary-0", + "platforms": ["macos"], + "summary": { + "en": "A static status look, on under Reduce Motion" + }, + "title": { + "en": "A static status look, on under Reduce Motion" + } + } + ], + "headline": { + "en": "A static status look, on under Reduce Motion" + }, + "schemaVersion": 1, + "version": "1.0.0-nightly.3913596493801" + } + }, + { + "build": "3913526554901", + "changes": [], + "date": "2026-10-18", + "head": "e11d7606ec7645d6dbe66a85c523a533f1f4e8d0", + "highlights": [], + "items": [ + { + "author": "Leo", + "pr": 21658, + "title": "fix(ci): send light-lane GUI suites to the std GUI runners, not Blacksmith" + }, + { + "author": "Lawrence Chen", + "title": "perf-gate: a tab switch is timed in the app (debug.tab_switch: intent to shown, to the next frame) and must show on the next frame; the socket reply, which waits for the daemon's confirm, is reported only (cx-8w027.21)" + } + ], + "shortVersion": "1.0.0-nightly.3913526554901", + "summary": [], + "version": 1 + }, + { + "build": "3913514606901", + "changes": [], + "date": "2026-10-18", + "head": "c25d784ff7cbe6cf5e705c9059c52466f88aa09b", + "highlights": [], + "items": [ + { + "author": "Leo", + "pr": 21645, + "title": "fix(cmux-next): restore composer row rhythm and open-chip wash" + }, + { + "author": "Leo", + "pr": 21646, + "title": "ci(cmux-next): run the split guard's classifier from the base" + }, + { + "author": "Lawrence Chen", + "title": "cmux NEXT perf-split: split budget lands in a follow-up push (perf-gate.py reserved by perf-fanout) (cx-8w027.14)" + }, + { + "author": "Leo", + "pr": 21640, + "title": "cmux NEXT: an agent page that never paints drops its loading spinner after 8 s (cx-txnr)" + }, + { + "author": "Lawrence Chen", + "title": "cmux NEXT perf-split: TabModel.focusSurface; expectations by tab id inline (CmuxNextApp size cap) (cx-8w027.14)" + }, + { + "author": "Leo", + "pr": 20211, + "title": "cx-6so.49: respawn a terminal whose host ended at the orphan grace" + }, + { + "author": "Leo", + "pr": 20765, + "title": "cmux NEXT: Retry Now and Restart cmux-tui on the not-connected screens (cx-jniyz.1)" + }, + { + "author": "Lawrence Chen", + "title": "perf-gate: relaunch waits for the restore to end (every terminal of the grid live, tab lists and counters still for 3 reads) before it measures (cx-8w027.20)" + }, + { + "author": "Lawrence Chen", + "title": "perf-gate: relaunch checks the grid's New Tab pages came back and lets the restore settle before it measures (cx-8w027.20, review)" + }, + { + "author": "Lawrence Chen", + "title": "cmux NEXT perf-fanout: a restored New Tab page reads no tab list in its pane's snapshot (cx-8w027.20)" + }, + { + "author": "Lawrence Chen", + "title": "perf-gate: a relaunch scenario: tabs and split again in the grid the app restored on the same tag (cx-8w027.20)" + }, + { + "author": "Lawrence Chen", + "title": "cmux NEXT perf-split: review: name which tabs a surface expectation finds; the optimistic split keeps its view (cx-8w027.14)" + }, + { + "author": "Lawrence Chen", + "title": "cmux NEXT perf-split: a tab the window minted is named by its id; the daemon's confirm sends no topology (split 2 topology per pair) (cx-8w027.14)" + } + ], + "shortVersion": "1.0.0-nightly.3913514606901", + "summary": [ + { + "group": "fixed", + "title": "Restore composer row rhythm and open-chip wash" + }, + { + "group": "changed", + "title": "An agent page that never paints drops its loading spinner after 8 s" + }, + { + "group": "changed", + "title": "Respawn a terminal whose host ended at the orphan grace" + }, + { + "group": "changed", + "title": "Retry Now and Restart cmux-tui on the not-connected screens" + }, + { + "group": "changed", + "title": "Cmux NEXT perf-fanout: a restored New Tab page reads no tab list in its pane's snapshot" + }, + { + "group": "changed", + "title": "Cmux NEXT perf-split: review: name which tabs a surface expectation finds; the…" + } + ], + "version": 1, + "whatsNew": { + "channel": "nightly", + "date": "2026-10-18", + "entries": [ + { + "audience": "all", + "category": "fixed", + "docs": "https://cmux.com/docs/changelog", + "id": "summary-0", + "platforms": ["macos"], + "summary": { + "en": "Restore composer row rhythm and open-chip wash" + }, + "title": { + "en": "Restore composer row rhythm and open-chip wash" + } + }, + { + "audience": "all", + "category": "improved", + "docs": "https://cmux.com/docs/changelog", + "id": "summary-1", + "platforms": ["macos"], + "summary": { + "en": "An agent page that never paints drops its loading spinner after 8 s" + }, + "title": { + "en": "An agent page that never paints drops its loading spinner…" + } + }, + { + "audience": "all", + "category": "improved", + "docs": "https://cmux.com/docs/changelog", + "id": "summary-2", + "platforms": ["macos"], + "summary": { + "en": "Respawn a terminal whose host ended at the orphan grace" + }, + "title": { + "en": "Respawn a terminal whose host ended at the orphan grace" + } + }, + { + "audience": "all", + "category": "improved", + "docs": "https://cmux.com/docs/changelog", + "id": "summary-4", + "platforms": ["macos"], + "summary": { + "en": "Cmux NEXT perf-fanout: a restored New Tab page reads no tab list in its pane's snapshot" + }, + "title": { + "en": "Cmux NEXT perf-fanout: a restored New Tab page reads no…" + } + }, + { + "audience": "all", + "category": "improved", + "docs": "https://cmux.com/docs/changelog", + "id": "summary-5", + "platforms": ["macos"], + "summary": { + "en": "Cmux NEXT perf-split: review: name which tabs a surface expectation finds; the…" + }, + "title": { + "en": "Cmux NEXT perf-split: review: name which tabs a surface…" + } + } + ], + "headline": { + "en": "Restore composer row rhythm and open-chip wash" + }, + "schemaVersion": 1, + "version": "1.0.0-nightly.3913514606901" + } + }, + { + "build": "3913267407001", + "changes": [], + "date": "2026-10-18", + "head": "a4d3373f82a51588885e44016824b3866759df68", + "highlights": [], + "items": [ + { + "author": "Leo", + "pr": 21630, + "title": "cmux NEXT: a thought dates its first and latest chunk" + }, + { + "author": "Leo", + "pr": 21629, + "title": "plan(next): workspace auto-naming that keeps up (hq#1957)" + }, + { + "author": "Leo", + "pr": 21626, + "title": "CmuxNext: a tab dropped on a strip lands by the pointer (cx-6ggef)" + }, + { + "author": "Leo", + "pr": 21636, + "title": "ci(gallery-link): post one PR receipt with commit, checks and app" + }, + { + "author": "Lawrence Chen", + "title": "perf(cmux-next): PointerHover refresh reads one window's targets (cx-8w027.10 c)" + }, + { + "author": "Lawrence Chen", + "title": "cmux NEXT perf-palette: terminal colors blend with the window on a theme change (GhosttyNextKit e4831af81, cx-8w027.11)" + }, + { + "author": "Lawrence Chen", + "title": "cmux-next: prefetch review fixes (service asks beside the start, EINTR, mark slots for first_window, .object literals)" + }, + { + "author": "Lawrence Chen", + "title": "cmux-next: drop the early GPU channel feature (no measured effect on the first window's wait)" + }, + { + "author": "Lawrence Chen", + "title": "cmux-next: ask CoreLocation and LocalAuthentication off the main thread before Chromium does" + }, + { + "author": "Lawrence Chen", + "title": "cmux-next: establish Chromium's GPU channel early; time CefInitialize's own call and the ready hooks" + }, + { + "author": "Lawrence Chen", + "title": "os-smoke: print the deeper stack of each long stall of the cold first tab" + }, + { + "author": "Lawrence Chen", + "title": "cmux-next: read the Chromium framework into the file cache before CefInitialize" + }, + { + "author": "Lawrence Chen", + "title": "cmux-next: time Chromium's start steps (debug.cef start_steps); os-smoke prints the cold first tab's timeline" + } + ], + "shortVersion": "1.0.0-nightly.3913267407001", + "summary": [ + { + "group": "changed", + "title": "A thought dates its first and latest chunk" + }, + { + "group": "changed", + "title": "A tab dropped on a strip lands by the pointer" + }, + { + "group": "changed", + "title": "Cmux NEXT perf-palette: terminal colors blend with the window on a theme change" + }, + { + "group": "changed", + "title": "Drop the early GPU channel feature (no measured effect on the first window's wait)" + } + ], + "version": 1, + "whatsNew": { + "channel": "nightly", + "date": "2026-10-18", + "entries": [ + { + "audience": "all", + "category": "improved", + "docs": "https://cmux.com/docs/changelog", + "id": "summary-0", + "platforms": ["macos"], + "summary": { + "en": "A thought dates its first and latest chunk" + }, + "title": { + "en": "A thought dates its first and latest chunk" + } + }, + { + "audience": "all", + "category": "improved", + "docs": "https://cmux.com/docs/changelog", + "id": "summary-1", + "platforms": ["macos"], + "summary": { + "en": "A tab dropped on a strip lands by the pointer" + }, + "title": { + "en": "A tab dropped on a strip lands by the pointer" + } + }, + { + "audience": "all", + "category": "improved", + "docs": "https://cmux.com/docs/changelog", + "id": "summary-2", + "platforms": ["macos"], + "summary": { + "en": "Cmux NEXT perf-palette: terminal colors blend with the window on a theme change" + }, + "title": { + "en": "Cmux NEXT perf-palette: terminal colors blend with the…" + } + }, + { + "audience": "all", + "category": "improved", + "docs": "https://cmux.com/docs/changelog", + "id": "summary-3", + "platforms": ["macos"], + "summary": { + "en": "Drop the early GPU channel feature (no measured effect on the first window's wait)" + }, + "title": { + "en": "Drop the early GPU channel feature (no measured effect on…" + } + } + ], + "headline": { + "en": "A thought dates its first and latest chunk" + }, + "schemaVersion": 1, + "version": "1.0.0-nightly.3913267407001" + } + }, + { + "build": "3913107309201", + "changes": [], + "date": "2026-10-18", + "head": "c15ae68b2f7a1e2f7683c82b7c092f26e6bfc9f5", + "highlights": [], + "items": [ + { + "author": "Leo", + "pr": 21592, + "title": "fix(cmux-next): restore workspace title motion tunable" + }, + { + "author": "Lawrence Chen", + "title": "perf-gate: a switch budget of 0 sidebar row configures and 0 band updates (cx-8w027.17)" + }, + { + "author": "Lawrence Chen", + "title": "sidebar: drop a stray fragment from the bandsDrawSelectionChange removal (cx-8w027.17)" + }, + { + "author": "Lawrence Chen", + "title": "sidebar: a top-item selection repaints the old and new item; no band update, no list reload (cx-8w027.17)" + }, + { + "author": "Lawrence Chen", + "title": "perf-gate: sidebar list reloads name their caller (debug.sidebar_perf list_reloads@file:line; the gate prints them per switch) (cx-8w027.17)" + }, + { + "author": "Leo", + "pr": 21245, + "title": "docs: add acpmux agent coordination skill" + }, + { + "author": "Leo", + "pr": 21171, + "title": "docs(agent-chat): propose progressive transcript disclosure" + }, + { + "author": "Leo", + "pr": 20722, + "title": "cmux-tui: workspace list in the cmux app lists the sidebar order" + }, + { + "author": "Leo", + "pr": 20043, + "title": "test(cmux-next): CSI 996 reports dark for a plain theme in dark mode" + }, + { + "author": "Leo", + "pr": 21190, + "title": "fix(cmux-next): avoid invisible divider occlusion holes" + }, + { + "author": "Leo", + "pr": 21152, + "title": "fix(cmux-next): theme the tab overflow action accent" + }, + { + "author": "Leo", + "pr": 21126, + "title": "fix(cmux-next): expose workspace selection to accessibility" + }, + { + "author": "Lawrence Chen", + "title": "cmux NEXT perf-split: split snapshot budget stays 4 (the shell's titles vary); base-red skip for acpmux protocol_ir_is_current (cx-gz5dx) (cx-8w027.14)" + }, + { + "author": "Lawrence Chen", + "title": "cmux-next strip: a moving column keeps the larger traffic-light inset until it rests" + }, + { + "author": "Lawrence Chen", + "title": "cmux NEXT perf-split: budget comment names only proven causes (cx-8w027.14)" + }, + { + "author": "Lawrence Chen", + "title": "cmux NEXT perf-split: split+close budget 2 applies, 3 topology sends, 3 snapshots per pair (measured, cx-8w027.14)" + }, + { + "author": "Lawrence Chen", + "title": "motion-record strip: also scroll with the sidebar hidden, the strip under the traffic lights" + }, + { + "author": "Lawrence Chen", + "title": "Revert \"cmux-next strip: terminals in the keep-alive band keep drawing, so a column scrolled in is never blank\"" + }, + { + "author": "Lawrence Chen", + "title": "strip-scroll-check: camera from the prompt text overlap, the pills' consensus where no text is shared; text extent from a resting frame" + }, + { + "author": "Lawrence Chen", + "title": "cmux NEXT perf-split: snapshot sources name a new pane's first runs (cx-8w027.14)" + }, + { + "author": "Lawrence Chen", + "title": "cmux NEXT perf-split: list split-client-split-id-v1 for the same-tree identify check; spec names which layouts carry split_id (review, cx-8w027.14)" + }, + { + "author": "Lawrence Chen", + "title": "cmux NEXT perf-split: debug.layout_counters names the fields each pane snapshot re-run changed (cx-8w027.14)" + }, + { + "author": "Lawrence Chen", + "title": "strip-scroll-check: per-frame camera dx, pill rigidity, blank columns and motion start for a strip recording" + }, + { + "author": "Lawrence Chen", + "title": "cmux NEXT perf-split: WorkspaceBlueprint.capture matches the split's resourceID (cx-8w027.14)" + }, + { + "author": "Lawrence Chen", + "title": "cmux-next strip: terminals in the keep-alive band keep drawing, so a column scrolled in is never blank" + }, + { + "author": "Lawrence Chen", + "title": "cmux-next strip: a column's tab bar lays out for where its pane rests, never pinned to the traffic lights while the camera scrolls" + }, + { + "author": "Lawrence Chen", + "title": "cmux NEXT perf-split: the daemon names an optimistic split by its client-minted split_id; delete ScreenModel.splitNames (cx-8w027.14)" + }, + { + "author": "Lawrence Chen", + "title": "motion-record: strip surface, focus left/right across a scrolling strip of tabbed columns" + } + ], + "shortVersion": "1.0.0-nightly.3913107309201", + "summary": [ + { + "group": "fixed", + "title": "Restore workspace title motion tunable" + }, + { + "group": "fixed", + "title": "Avoid invisible divider occlusion holes" + }, + { + "group": "fixed", + "title": "Theme the tab overflow action accent" + }, + { + "group": "fixed", + "title": "Expose workspace selection to accessibility" + }, + { + "group": "changed", + "title": "A moving column keeps the larger traffic-light inset until it rests" + }, + { + "group": "changed", + "title": "Cmux NEXT perf-split: snapshot sources name a new pane's first runs" + }, + { + "group": "changed", + "title": "Terminals in the keep-alive band keep drawing, so a column scrolled in is never blank" + }, + { + "group": "changed", + "title": "A column's tab bar lays out for where its pane rests, never pinned to the traffic lights…" + } + ], + "version": 1, + "whatsNew": { + "channel": "nightly", + "date": "2026-10-18", + "entries": [ + { + "audience": "all", + "category": "fixed", + "docs": "https://cmux.com/docs/changelog", + "id": "summary-0", + "platforms": ["macos"], + "summary": { + "en": "Restore workspace title motion tunable" + }, + "title": { + "en": "Restore workspace title motion tunable" + } + }, + { + "audience": "all", + "category": "fixed", + "docs": "https://cmux.com/docs/changelog", + "id": "summary-1", + "platforms": ["macos"], + "summary": { + "en": "Avoid invisible divider occlusion holes" + }, + "title": { + "en": "Avoid invisible divider occlusion holes" + } + }, + { + "audience": "all", + "category": "fixed", + "docs": "https://cmux.com/docs/changelog", + "id": "summary-2", + "platforms": ["macos"], + "summary": { + "en": "Theme the tab overflow action accent" + }, + "title": { + "en": "Theme the tab overflow action accent" + } + }, + { + "audience": "all", + "category": "fixed", + "docs": "https://cmux.com/docs/changelog", + "id": "summary-3", + "platforms": ["macos"], + "summary": { + "en": "Expose workspace selection to accessibility" + }, + "title": { + "en": "Expose workspace selection to accessibility" + } + }, + { + "audience": "all", + "category": "improved", + "docs": "https://cmux.com/docs/changelog", + "id": "summary-4", + "platforms": ["macos"], + "summary": { + "en": "A moving column keeps the larger traffic-light inset until it rests" + }, + "title": { + "en": "A moving column keeps the larger traffic-light inset until…" + } + }, + { + "audience": "all", + "category": "improved", + "docs": "https://cmux.com/docs/changelog", + "id": "summary-5", + "platforms": ["macos"], + "summary": { + "en": "Cmux NEXT perf-split: snapshot sources name a new pane's first runs" + }, + "title": { + "en": "Cmux NEXT perf-split: snapshot sources name a new pane's…" + } + }, + { + "audience": "all", + "category": "improved", + "docs": "https://cmux.com/docs/changelog", + "id": "summary-6", + "platforms": ["macos"], + "summary": { + "en": "Terminals in the keep-alive band keep drawing, so a column scrolled in is never blank" + }, + "title": { + "en": "Terminals in the keep-alive band keep drawing, so a column…" + } + }, + { + "audience": "all", + "category": "improved", + "docs": "https://cmux.com/docs/changelog", + "id": "summary-7", + "platforms": ["macos"], + "summary": { + "en": "A column's tab bar lays out for where its pane rests, never pinned to the traffic lights…" + }, + "title": { + "en": "A column's tab bar lays out for where its pane rests,…" + } + } + ], + "headline": { + "en": "Restore workspace title motion tunable" + }, + "schemaVersion": 1, + "version": "1.0.0-nightly.3913107309201" + } + }, + { + "build": "3912903869801", + "changes": [], + "date": "2026-10-18", + "head": "f5fdfe063ac82d29264f47bc9e140f07c38ddfe1", + "highlights": [], + "items": [ + { + "author": "Leo", + "pr": 21281, + "title": "feat(cmux-next): add responsive priority sidebar ordering" + } + ], + "shortVersion": "1.0.0-nightly.3912903869801", + "summary": [ + { + "group": "new", + "title": "Add responsive priority sidebar ordering" + } + ], + "version": 1, + "whatsNew": { + "channel": "nightly", + "date": "2026-10-18", + "entries": [ + { + "audience": "all", + "category": "new", + "docs": "https://cmux.com/docs/changelog", + "id": "summary-0", + "platforms": ["macos"], + "summary": { + "en": "Add responsive priority sidebar ordering" + }, + "title": { + "en": "Add responsive priority sidebar ordering" + } + } + ], + "headline": { + "en": "Add responsive priority sidebar ordering" + }, + "schemaVersion": 1, + "version": "1.0.0-nightly.3912903869801" + } + }, + { + "build": "3912866882501", + "changes": [], + "date": "2026-10-18", + "head": "03065a96654b5b0a7dd286659f24405f97c55ea4", + "highlights": [], + "items": [ + { + "author": "Leo", + "pr": 21612, + "title": "test(next): isolate cloud bring-back cases" + } + ], + "shortVersion": "1.0.0-nightly.3912866882501", + "summary": [], + "version": 1 + }, + { + "build": "3912814684901", + "changes": [], + "date": "2026-10-18", + "head": "ef0c4a3f6ff4a1a19961dc42b40db1ca3bd630b4", + "highlights": [], + "items": [ + { + "author": "Leo", + "pr": 21583, + "title": "ci: cache cmux-next fast-tier builds" + } + ], + "shortVersion": "1.0.0-nightly.3912814684901", + "summary": [], + "version": 1 + }, + { + "build": "3912754417501", + "changes": [], + "date": "2026-10-18", + "head": "e04ac062c1a73dc7d89e850295892e655d210155", + "highlights": [], + "items": [ + { + "author": "Leo", + "pr": 21577, + "title": "ci(next): keep post-publication checks off the feed gate" + }, + { + "author": "Lawrence Chen", + "title": "ci: the scheme binary-module guard clears only a DerivedData with outputs, keeps its digest through a stale-module retry, shows a failed resolve (review, cx-8w027.7)" + }, + { + "author": "Lawrence Chen", + "title": "ci: the scheme binary-module guard makes DerivedData before its stamp (cx-8w027.7)" + }, + { + "author": "Lawrence Chen", + "title": "ci: the kept-DerivedData scheme and Release compiles build cold when a binary target's headers change (cx-8w027.7)" + } + ], + "shortVersion": "1.0.0-nightly.3912754417501", + "summary": [], + "version": 1 + }, + { + "build": "3912602396401", + "changes": [], + "date": "2026-10-18", + "head": "5addcb044de418a2341c8f3130a57274a1dfb726", + "highlights": [], + "items": [ + { + "author": "Leo", + "pr": 21566, + "title": "perf(acpmux): preserve normalized recent session entries" + }, + { + "author": "Lawrence Chen", + "title": "fix(cmux-next): fail the no-build capability check on a capability in two lists" + }, + { + "author": "Lawrence Chen", + "title": "fix(cmux-next): keep workspace-name-source-v1 only in the unserved list" + }, + { + "author": "Leo", + "pr": 21579, + "title": "ci(cmux-next): add advisory split-plan guard" + }, + { + "author": "Leo", + "pr": 21574, + "title": "fix(cmux-next): align composer control chrome" + }, + { + "author": "Leo", + "pr": 21591, + "title": "fix(ci): avoid dead GUI runner fallback" + }, + { + "author": "Leo", + "pr": 21530, + "title": "ci: plan OR guard conditions without native routing" + }, + { + "author": "Leo", + "pr": 21380, + "title": "acpmux: add host-qualified session receipts" + }, + { + "author": "Leo", + "pr": 21543, + "title": "fix(cmux-next): keep sidebar close and hover state local" + }, + { + "author": "Leo", + "pr": 21192, + "title": "ci: fetch only the nightly acpmux companion" + }, + { + "author": "Leo", + "pr": 21189, + "title": "ci: reuse cmux-next web bundles across Linux and macOS" + }, + { + "author": "Leo", + "pr": 21570, + "title": "ci: rebase rendered-state tour postconditions" + }, + { + "author": "Leo", + "pr": 21557, + "title": "perf(acpmux): skip inactive sidebar grouping" + }, + { + "author": "Lawrence Chen", + "title": "cmux-next: spare window rekey refuses another store instead of a precondition (crash ratchet)" + }, + { + "author": "Leo", + "pr": 21548, + "title": "fix(cmux-next): keep no-activate watchdog evidence alive" + }, + { + "author": "Lawrence Chen", + "title": "coordination: move the #21558 remote-link note out of COORDINATION.md" + }, + { + "author": "Leo", + "pr": 21532, + "title": "feat(gallery): add orchestration lab foundation" + }, + { + "author": "Leo", + "pr": 21445, + "title": "feat(cmux-next): persist auto names across capable daemons" + }, + { + "author": "Leo", + "pr": 21565, + "title": "ci: bound cmux-next ghostty initialization" + }, + { + "author": "Leo", + "pr": 21562, + "title": "cmux-next tours: surface degraded visual coverage" + }, + { + "author": "Leo", + "pr": 21286, + "title": "fix(cmux-next): stabilize tooltip and local browser restore tests" + }, + { + "author": "Lawrence Chen", + "title": "cmux-next: no spare Chromium window while a Chromium page is being created" + }, + { + "author": "Lawrence Chen", + "title": "os-smoke: observe lazy_launch past the launch preload delay; timeouts report stalls after the first tab" + }, + { + "author": "Lawrence Chen", + "title": "cmux-next: recent-use record from user tabs only; probe phase hardening (review)" + }, + { + "author": "Lawrence Chen", + "title": "cmux-next: warm Chromium at launch only after recent use; first-tab signals" + }, + { + "author": "Lawrence Chen", + "title": "cmux-next: a window that becomes the spare again is no longer the last shown pane" + }, + { + "author": "Lawrence Chen", + "title": "cmux-next: spare Chromium window review fixes" + }, + { + "author": "Lawrence Chen", + "title": "cmux-next: start Chromium and a spare window at idle moments after launch" + } + ], + "shortVersion": "1.0.0-nightly.3912602396401", + "summary": [ + { + "group": "new", + "title": "Persist auto names across capable daemons" + }, + { + "group": "fixed", + "title": "Align composer control chrome" + }, + { + "group": "fixed", + "title": "Keep sidebar close and hover state local" + }, + { + "group": "fixed", + "title": "Keep no-activate watchdog evidence alive" + }, + { + "group": "changed", + "title": "Preserve normalized recent session entries" + }, + { + "group": "changed", + "title": "Skip inactive sidebar grouping" + }, + { + "group": "changed", + "title": "Surface degraded visual coverage" + }, + { + "group": "changed", + "title": "No spare Chromium window while a Chromium page is being created" + } + ], + "version": 1, + "whatsNew": { + "channel": "nightly", + "date": "2026-10-18", + "entries": [ + { + "audience": "all", + "category": "new", + "docs": "https://cmux.com/docs/changelog", + "id": "summary-0", + "platforms": ["macos"], + "summary": { + "en": "Persist auto names across capable daemons" + }, + "title": { + "en": "Persist auto names across capable daemons" + } + }, + { + "audience": "all", + "category": "fixed", + "docs": "https://cmux.com/docs/changelog", + "id": "summary-1", + "platforms": ["macos"], + "summary": { + "en": "Align composer control chrome" + }, + "title": { + "en": "Align composer control chrome" + } + }, + { + "audience": "all", + "category": "fixed", + "docs": "https://cmux.com/docs/changelog", + "id": "summary-2", + "platforms": ["macos"], + "summary": { + "en": "Keep sidebar close and hover state local" + }, + "title": { + "en": "Keep sidebar close and hover state local" + } + }, + { + "audience": "all", + "category": "fixed", + "docs": "https://cmux.com/docs/changelog", + "id": "summary-3", + "platforms": ["macos"], + "summary": { + "en": "Keep no-activate watchdog evidence alive" + }, + "title": { + "en": "Keep no-activate watchdog evidence alive" + } + }, + { + "audience": "all", + "category": "improved", + "docs": "https://cmux.com/docs/changelog", + "id": "summary-4", + "platforms": ["macos"], + "summary": { + "en": "Preserve normalized recent session entries" + }, + "title": { + "en": "Preserve normalized recent session entries" + } + }, + { + "audience": "all", + "category": "improved", + "docs": "https://cmux.com/docs/changelog", + "id": "summary-5", + "platforms": ["macos"], + "summary": { + "en": "Skip inactive sidebar grouping" + }, + "title": { + "en": "Skip inactive sidebar grouping" + } + }, + { + "audience": "all", + "category": "improved", + "docs": "https://cmux.com/docs/changelog", + "id": "summary-6", + "platforms": ["macos"], + "summary": { + "en": "Surface degraded visual coverage" + }, + "title": { + "en": "Surface degraded visual coverage" + } + }, + { + "audience": "all", + "category": "improved", + "docs": "https://cmux.com/docs/changelog", + "id": "summary-7", + "platforms": ["macos"], + "summary": { + "en": "No spare Chromium window while a Chromium page is being created" + }, + "title": { + "en": "No spare Chromium window while a Chromium page is being…" + } + } + ], + "headline": { + "en": "Persist auto names across capable daemons" + }, + "schemaVersion": 1, + "version": "1.0.0-nightly.3912602396401" + } + }, + { + "build": "3911762409401", + "changes": [], + "date": "2026-10-18", + "head": "00e0785ea8e30aa85024a3c237bc5436ff95e5f7", + "highlights": [], + "items": [ + { + "author": "Leo", + "pr": 21312, + "title": "fix nested Swift Testing require" + }, + { + "author": "Leo", + "pr": 21546, + "title": "ci: guard PR autofix ancestry" + }, + { + "author": "Leo", + "pr": 21564, + "title": "fix(cmux-next): stabilize summary rail inline panel" + }, + { + "author": "Leo", + "pr": 21553, + "title": "perf(acpmux): cache immutable chat find text" + }, + { + "author": "Leo", + "pr": 21320, + "title": "perf(webviews): avoid redundant New Tab motion scans" + }, + { + "author": "Leo", + "pr": 21421, + "title": "fix(cmux-next): keep restored page tabs readable" + }, + { + "author": "Leo", + "pr": 21558, + "title": "Verify the selected daemon before reusing a remote sidecar" + }, + { + "author": "Leo", + "pr": 21433, + "title": "test: cover workspace renamed event display name" + }, + { + "author": "Leo", + "pr": 21536, + "title": "perf(next): index transcript row ids once per snapshot" + }, + { + "author": "Leo", + "pr": 21555, + "title": "ci(next): skip cached web bundle rebuilds" + } + ], + "shortVersion": "1.0.0-nightly.3911762409401", + "summary": [ + { + "group": "fixed", + "title": "Fix nested Swift Testing require" + }, + { + "group": "fixed", + "title": "Stabilize summary rail inline panel" + }, + { + "group": "fixed", + "title": "Keep restored page tabs readable" + }, + { + "group": "changed", + "title": "Cache immutable chat find text" + }, + { + "group": "changed", + "title": "Avoid redundant New Tab motion scans" + }, + { + "group": "changed", + "title": "Index transcript row ids once per snapshot" + } + ], + "version": 1, + "whatsNew": { + "channel": "nightly", + "date": "2026-10-18", + "entries": [ + { + "audience": "all", + "category": "fixed", + "docs": "https://cmux.com/docs/changelog", + "id": "summary-0", + "platforms": ["macos"], + "summary": { + "en": "Fix nested Swift Testing require" + }, + "title": { + "en": "Fix nested Swift Testing require" + } + }, + { + "audience": "all", + "category": "fixed", + "docs": "https://cmux.com/docs/changelog", + "id": "summary-1", + "platforms": ["macos"], + "summary": { + "en": "Stabilize summary rail inline panel" + }, + "title": { + "en": "Stabilize summary rail inline panel" + } + }, + { + "audience": "all", + "category": "fixed", + "docs": "https://cmux.com/docs/changelog", + "id": "summary-2", + "platforms": ["macos"], + "summary": { + "en": "Keep restored page tabs readable" + }, + "title": { + "en": "Keep restored page tabs readable" + } + }, + { + "audience": "all", + "category": "improved", + "docs": "https://cmux.com/docs/changelog", + "id": "summary-3", + "platforms": ["macos"], + "summary": { + "en": "Cache immutable chat find text" + }, + "title": { + "en": "Cache immutable chat find text" + } + }, + { + "audience": "all", + "category": "improved", + "docs": "https://cmux.com/docs/changelog", + "id": "summary-4", + "platforms": ["macos"], + "summary": { + "en": "Avoid redundant New Tab motion scans" + }, + "title": { + "en": "Avoid redundant New Tab motion scans" + } + }, + { + "audience": "all", + "category": "improved", + "docs": "https://cmux.com/docs/changelog", + "id": "summary-5", + "platforms": ["macos"], + "summary": { + "en": "Index transcript row ids once per snapshot" + }, + "title": { + "en": "Index transcript row ids once per snapshot" + } + } + ], + "headline": { + "en": "Fix nested Swift Testing require" + }, + "schemaVersion": 1, + "version": "1.0.0-nightly.3911762409401" + } + }, + { + "build": "3911418510901", + "changes": [], + "date": "2026-10-18", + "head": "40036060aad1e522871855fa8dda5ded624bf456", + "highlights": [], + "items": [ + { + "author": "Leo", + "pr": 21506, + "title": "fix(cmux-next): paint bundled startup model immediately" + }, + { + "author": "Leo", + "pr": 21417, + "title": "chore: refresh PR routing after full-ci removal" + }, + { + "author": "Leo", + "pr": 21338, + "title": "feat(cmux-next): add Apps update center" + }, + { + "author": "Leo", + "pr": 21241, + "title": "fix(composer): focus location footer rim" + }, + { + "author": "Leo", + "pr": 21515, + "title": "fix(cmux-next): preserve relative acpmux bundle alias" + } + ], + "shortVersion": "1.0.0-nightly.3911418510901", + "summary": [ + { + "group": "new", + "title": "Add Apps update center" + }, + { + "group": "fixed", + "title": "Paint bundled startup model immediately" + }, + { + "group": "fixed", + "title": "Focus location footer rim" + } + ], + "version": 1, + "whatsNew": { + "channel": "nightly", + "date": "2026-10-18", + "entries": [ + { + "audience": "all", + "category": "new", + "docs": "https://cmux.com/docs/changelog", + "id": "summary-0", + "platforms": ["macos"], + "summary": { + "en": "Add Apps update center" + }, + "title": { + "en": "Add Apps update center" + } + }, + { + "audience": "all", + "category": "fixed", + "docs": "https://cmux.com/docs/changelog", + "id": "summary-1", + "platforms": ["macos"], + "summary": { + "en": "Paint bundled startup model immediately" + }, + "title": { + "en": "Paint bundled startup model immediately" + } + }, + { + "audience": "all", + "category": "fixed", + "docs": "https://cmux.com/docs/changelog", + "id": "summary-2", + "platforms": ["macos"], + "summary": { + "en": "Focus location footer rim" + }, + "title": { + "en": "Focus location footer rim" + } + } + ], + "headline": { + "en": "Add Apps update center" + }, + "schemaVersion": 1, + "version": "1.0.0-nightly.3911418510901" + } + }, + { + "build": "3911131892801", + "changes": [], + "date": "2026-10-18", + "head": "47b6ba2d271c2d6db3bbe30503ed8e03a59d72bb", + "highlights": [], + "items": [ + { + "author": "Leo", + "pr": 21538, + "title": "fix(cmux-next): avoid duplicate base archive pathspec" + }, + { + "author": "Leo", + "pr": 21535, + "title": "perf(next): coalesce activity bridge state pushes" + }, + { + "author": "Leo", + "pr": 21533, + "title": "ci(next): retire release-surface approval bottleneck" + }, + { + "author": "Leo Li", + "title": "fix(cmux-next): release superseded space pager lock" + }, + { + "author": "Leo", + "title": "ci: declare workspace name capability unserved" + }, + { + "author": "Leo", + "pr": 21264, + "title": "test agent chat Codex parity stream" + }, + { + "author": "Leo", + "pr": 21157, + "title": "fix(next): refresh static verification inputs" + }, + { + "author": "Leo", + "pr": 21193, + "title": "ci: explain nightly-next safety holds in decision summary" + }, + { + "author": "Leo", + "pr": 21391, + "title": "polish(cmux-next): round composer pills and highlights" + }, + { + "author": "Leo", + "pr": 21522, + "title": "fix(cmux-next): fail closed for unsupported workspace name provenance" + }, + { + "author": "Leo Li", + "title": "fix(cmux-next): preserve acpmux bundle alias" + }, + { + "author": "Leo", + "pr": 21270, + "title": "ci(next): validate sidebar performance receipts" + }, + { + "author": "Leo", + "pr": 21501, + "title": "perf(webviews): release completed list motion animations" + }, + { + "author": "Leo", + "pr": 21321, + "title": "fix: bind review findings to exact run heads" + }, + { + "author": "Leo", + "pr": 21500, + "title": "perf(cmux-next): avoid sorting lanes twice for sidebar badge" + }, + { + "author": "Leo", + "pr": 21496, + "title": "fix: keep no-activate LaunchServices off main" + }, + { + "author": "Leo", + "pr": 21493, + "title": "test(cmux-next): gate GUI motion checks on real display frames" + }, + { + "author": "Leo", + "pr": 21395, + "title": "fix(cmux-next): show focus rings only for keyboard navigation" + }, + { + "author": "Leo", + "pr": 21512, + "title": "Add sidebar preview and reasoning slider gallery foundation" + }, + { + "author": "Leo", + "pr": 21511, + "title": "fix(cmux-next): split runtime motion and control fixes" + }, + { + "author": "Leo", + "pr": 21510, + "title": "fix(cmux-next): split source-size guard tooling" + }, + { + "author": "Leo", + "pr": 21509, + "title": "fix(composer): preserve draft hydration across relaunch" + }, + { + "author": "Leo", + "pr": 21459, + "title": "fix(cmux-next): move focus after closing a tab group" + }, + { + "author": "Leo", + "pr": 21504, + "title": "ci(cmux-next): broaden product path admission" + }, + { + "author": "Leo", + "pr": 21461, + "title": "feat(gallery): add faithful effort track preview" + }, + { + "author": "Leo", + "pr": 21441, + "title": "feat(next): carry workspace name provenance in Swift daemon client" + }, + { + "author": "Leo", + "title": "polish(cmux-next): let composer surfaces reveal page backgrounds" + }, + { + "author": "Leo", + "title": "rebase nightly whats-new fix onto current cmux-next" + }, + { + "author": "Lawrence Chen", + "title": "cmux-next: engine start credit follows the request (review fixes)" + }, + { + "author": "Lawrence Chen", + "title": "cmux-next: control deadlines skip main-thread time in Chromium's start" + }, + { + "author": "Lawrence Chen", + "title": "os-smoke: sample the app across the first Chromium tab and print CefInitialize timing and long main-thread stalls" + }, + { + "author": "Leo", + "pr": 21494, + "title": "fix(cmux-next): preserve base measurements in god-file guard" + }, + { + "author": "Leo", + "pr": 21476, + "title": "perf(webviews): harden list motion invalidation lifecycle" + }, + { + "author": "Leo", + "pr": 21475, + "title": "perf(agent-activity): ignore stale priority events" + }, + { + "author": "Lawrence Chen", + "title": "divider-drag-reflow-live.py: owner-grid lag is reported, not failed; the drawn grid carries the 0-lag pass" + }, + { + "author": "Lawrence Chen", + "title": "perf-tabs-polish: a pinned band end keeps its scroll share under the scroll key; a frame the crop cannot cut is dropped (cx-8w027.18)" + }, + { + "author": "Leo", + "pr": 21471, + "title": "perf(cmux-next): avoid sorting lane IDs on updates" + }, + { + "author": "Lawrence Chen", + "title": "perf-tabs-polish: parts step where the tab changes form (x or title shows or hides, the title starts to clip) instead of moving across it, as a per-frame relayout does (cx-8w027.18)" + }, + { + "author": "Lawrence Chen", + "title": "perf-switch2: a view that goes live hidden stops counting at once; the GUI reads shared-sizing-v1 without advertising it (review) (cx-8w027.9)" + }, + { + "author": "Lawrence Chen", + "title": "debug.frames reports when each missed vsync happened (missed_at_ms)" + }, + { + "author": "Lawrence Chen", + "title": "perf-tabs-polish: frame_strip crop to the tab strip (full-scale strip proofs) (cx-8w027.18)" + }, + { + "author": "Lawrence Chen", + "title": "perf-switch2: shared-sizing-v1 is an optional daemon capability of the app (cx-8w027.9)" + }, + { + "author": "Lawrence Chen", + "title": "perf-reflow: the preview follows the geometry claim; the proof needs preview frames (review)" + }, + { + "author": "Lawrence Chen", + "title": "cmux NEXT perf-reflow: a terminal's text fits a resized pane on the same frame (GhosttyNextKit c5926d664, cx-8w027.13)" + }, + { + "author": "Lawrence Chen", + "title": "perf-switch2: a hidden terminal view keeps its lease and claim and stops counting toward the grid (cx-8w027.9)" + }, + { + "author": "Lawrence Chen", + "title": "macho_minos.py: name every /usr/lib/swift dylib that macOS 14 lacks (cx-sisy8 follow-up)" + }, + { + "author": "Lawrence Chen", + "title": "cmux-tui: graphics writer cancel cannot lose a condvar wakeup" + }, + { + "author": "Lawrence Chen", + "title": "perf-switch2: agent cursor finds a released workspace's window by membership; park takes its serial (review) (cx-8w027.10)" + }, + { + "author": "Lawrence Chen", + "title": "perf-tabs-polish: review fixes: scroll-only layers cancel out, occlusion keyframes start now, no marquee on a path, pinned band end excludes the scroll part; full-scale strip overview capped (cx-8w027.18)" + }, + { + "author": "Lawrence Chen", + "title": "perf-switch2: mounted workspaces in park order; critical memory pressure releases parked ones (cx-8w027.10)" + }, + { + "author": "Lawrence Chen", + "title": "perf-switch2: code that meant in-window as visible checks hidden too (review) (cx-8w027.10)" + }, + { + "author": "Lawrence Chen", + "title": "perf-tabs-polish: import CmuxNextDesign for MotionPath in TabCell+Motion (cx-8w027.18)" + }, + { + "author": "Lawrence Chen", + "title": "ci: binary-module guard removes every build output on a header change (fleet-pcm)" + }, + { + "author": "Lawrence Chen", + "title": "perf-tabs-polish: strip motion exact on the render server: parts follow the width path, exact occlusion paths, band end, wheel ends a relayout's scroll (cx-8w027.18)" + }, + { + "author": "Leo", + "pr": 21453, + "title": "ci(web): run React Doctor in parallel" + }, + { + "author": "Leo", + "pr": 21440, + "title": "docs: make cmux-next ACPmux event ownership explicit" + }, + { + "author": "Lawrence Chen", + "title": "perf-switch2: hidden workspace trees stay out of window-wide fan-outs (cx-8w027.10)" + }, + { + "author": "Lawrence Chen", + "title": "perf-gate: re-review fixes: signal exit code kept, landed read inside its window, ratchet only on clean full runs (cx-8w027.7)" + }, + { + "author": "Lawrence Chen", + "title": "perf-gate: review fixes: known breach max, ratchet only on full runs, landed checks, quiet counter reads, crash and teardown safety (cx-8w027.7)" + }, + { + "author": "Lawrence Chen", + "title": "bench_pane_scale: --tabs adds New Tab Page tabs (newTab is New Workspace) (cx-8w027.7)" + }, + { + "author": "Lawrence Chen", + "title": "perf-gate: its own check job (a breach never fails the app-producing job), Next Tab sanity (cx-8w027.7)" + }, + { + "author": "Lawrence Chen", + "title": "perf-gate: 4x4 grid by targeted splits, New Tab Page tabs (cx-8w027.7)" + }, + { + "author": "Lawrence Chen", + "title": "perf-gate: one-screen 16-pane grid, known-breach ratchet (cx-8w027.17), workflow step (cx-8w027.7)" + }, + { + "author": "Lawrence Chen", + "title": "perf-gate: one-launch counter budget gate for switch, theme, drag, tabs, split and status (cx-8w027.7)" + }, + { + "author": "Lawrence Chen", + "title": "perf-switch2: a parked workspace stays in its window, hidden; no window re-entry on a switch (cx-8w027.10)" + }, + { + "author": "Leo", + "title": "rebase focused streaming motion after Chief Dock" + }, + { + "author": "Leo", + "pr": 21194, + "title": "rebase focused work onto current cmux-next" + }, + { + "author": "Lawrence Chen", + "title": "cmux NEXT perf-split: the daemon's echo of an optimistic split does no work (cx-8w027.14)" + }, + { + "author": "Leo", + "title": "merge #21363 exact-head green" + }, + { + "author": "Leo", + "title": "merge #21344 exact-head green" + }, + { + "author": "Leo", + "pr": 21419, + "title": "test(web): await installed empty state" + }, + { + "author": "Lawrence Chen", + "title": "ci: binary-module guard digests only the xcframeworks a manifest names; a failed resolve drops the stamp (review)" + }, + { + "author": "Lawrence Chen", + "title": "ci: a warm SwiftPM .build drops its precompiled modules when a binary target's headers change (fleet-pcm, cx-8w027)" + }, + { + "author": "Leo", + "pr": 21442, + "title": "Gallery: make current-composer handoff fast and shareable" + }, + { + "author": "Leo", + "pr": 21450, + "title": "fix(setup): install hooks before toolchain checks" + }, + { + "author": "Lawrence Chen", + "title": "cmux-next: ChromeLabel hides its glyphs when it turns editable (review, cx-8w027.12)" + }, + { + "author": "Lawrence Chen", + "title": "cmux-next perf-tabs: the scroll probe takes each reveal's own delta; a reveal never delays a closing tab" + }, + { + "author": "Lawrence Chen", + "title": "cmux-next perf-tabs: debug.motion samples the strip's move travel off the presentation layers while it records" + }, + { + "author": "Lawrence Chen", + "title": "perf-switch: a parked workspace stops following its attention rings (cx-8w027.10)" + }, + { + "author": "Lawrence Chen", + "title": "cmux-next perf-tabs: second review fixes for the CA strip moves" + }, + { + "author": "Lawrence Chen", + "title": "cmux-next: ChromeLabel: ScrollEdgeFadeView.rendersTopDown (cx-8w027.12)" + }, + { + "author": "Leo", + "pr": 21384, + "title": "perf(cmux-next): gate find highlight repaints by transcript changes" + }, + { + "author": "Leo", + "pr": 21446, + "title": "test(apps): tolerate empty-state selector rename" + }, + { + "author": "Lawrence Chen", + "title": "cmux-next perf-tabs: review fixes for the CA strip moves" + }, + { + "author": "Leo", + "pr": 21383, + "title": "perf(acpmux): reserve prompt image slots during host load" + }, + { + "author": "Lawrence Chen", + "title": "cmux-next: ChromeLabel review fixes: selectable labels blend and keep selection (glyphs hide while the field editor shows), glyph mask at whole pixels anchored to the top edge, stale stock backing cleared; drag-lift count badge and sidebar item title stay NSTextField (layer.render skips masks) (cx-8w027.12)" + }, + { + "author": "Lawrence Chen", + "title": "generated: daemon-capabilities.json lists conversation-tab-split-v1 (lost in the merge)" + }, + { + "author": "Lawrence Chen", + "title": "cmux-next perf-tabs: main-proof note on the move completion line" + }, + { + "author": "Lawrence Chen", + "title": "cmux-next perf-tabs: closing-mode hit reads the places; motion-proof --crowded strip gestures" + }, + { + "author": "Leo", + "pr": 21422, + "title": "feat(cmux-next): wire ACPmux events into priority agent view" + }, + { + "author": "Lawrence Chen", + "title": "cmux-next: ChromeLabel renders its glyph mask image in updateLayer (main actor, no layer draw callback); selectable and editable fields draw the stock way; selectable labels stay NSTextField (cx-8w027.12)" + }, + { + "author": "Lawrence Chen", + "title": "cmux-next: pin CCmuxAppFFI to cmux-app-ffi-b17c7f9395f1 (JSON focus ops deleted) (cx-8w027.2)" + }, + { + "author": "Lawrence Chen", + "title": "cmux NEXT perf-observe: a split or close does no extra apply, topology send or snapshot (cx-8w027.1)" + }, + { + "author": "Lawrence Chen", + "title": "cmux-next perf-tabs: Core Animation tab strip motion, no per-frame stepping" + }, + { + "author": "Lawrence Chen", + "title": "cmux-next: ChromeLabel draws its own NSTextField cell once as the glyph mask of a fill layer (wrapping, multi-line, any alignment); ThemedLabel and the themed labels of hover cards, notices, panels, banners and tab bar extras use it, so their text blends on a theme change (cx-8w027.12)" + }, + { + "author": "Lawrence Chen", + "title": "cmux-next: web page hosts follow their theme scope as a responder: every color change pushes to the page shown or hidden, so a page shown after a change paints its first frame in the new colors; drop the push on unhide (cx-8w027.12)" + }, + { + "author": "Lawrence Chen", + "title": "perf-switch: a presence change reads one owner's surfaces, not every presented key (cx-8w027.10)" + }, + { + "author": "Lawrence Chen", + "title": "input-spec: release builds keep the automatic input invariant check off (lead decision 2026-10-18, cx-8w027.2)" + }, + { + "author": "Lawrence Chen", + "title": "cmux-focus-core: delete the whole-state JSON focus ops (focus_reduce, focus_changes_view); the app uses only the cmux_focus_* handle since 2a893508ebb2 (cx-8w027.2)" + }, + { + "author": "Lawrence Chen", + "title": "generated: defaults snapshot follows PaneSplitCommand into CmuxNextDaemonService" + }, + { + "author": "Leo", + "pr": 21397, + "title": "feat(next): carry explicit session lifecycle receipts" + }, + { + "author": "Lawrence Chen", + "title": "check-app-capability-references: 5.9 s -> 1.7 s, same output" + }, + { + "author": "Lawrence Chen", + "title": "perf-layout: a claim of the announced grid expects no echo; proof script measures the drag alone (review)" + }, + { + "author": "Lawrence Chen", + "title": "divider-drag-reflow-live.py reads each terminal's rendered and fitted grid (surface.grid, surface.fit_grid)" + }, + { + "author": "Lawrence Chen", + "title": "cmux NEXT perf-layout: a divider drag reflows the terminal on every frame (cx-8w027.6, cx-8w027.8)" + }, + { + "author": "Lawrence Chen", + "title": "cmux NEXT perf-layout: a terminal keeps its last frame during a pane drag (host-sized GhosttyNextKit 48d353b8c, cx-8w027.8)" + }, + { + "author": "Lawrence Chen", + "title": "perf-focus: the input invariant check is one deadline, debug builds only (no per-frame stepping; debug.desync checks on demand in any build) (cx-8w027.2)" + }, + { + "author": "Lawrence Chen", + "title": "cmux-next: ChromeTextLayer redraws its glyph mask on a scale change; ChromeLabel follows the window's backing scale (review, cx-8w027.3)" + }, + { + "author": "Lawrence Chen", + "title": "cmux-next: chrome text color is a layer color: ChromeTextLayer draws its glyphs once as the mask of a fill layer, ChromeLabel draws an AppKit label that way (sidebar row labels, titlebar title), so a theme change blends text on the render server from the color on screen (I5, cx-8w027.3, Lawrence 10-17)" + }, + { + "author": "Leo", + "pr": 21438, + "title": "ci: route bot rescue attempt three to Blacksmith" + }, + { + "author": "Lawrence Chen", + "title": "cmux NEXT: split-atomic-record.py records a person's Cmd-D from a New Tab page and checks no read shows the page in the source strip" + }, + { + "author": "Lawrence Chen", + "title": "cmux-next perf-tabs: main-actor-ok for the moved viewport line split; lower the ratchet baseline" + }, + { + "author": "Lawrence Chen", + "title": "cmux NEXT: Cmd-D from a New Tab page or chat opens the page in a new split in one daemon commit" + }, + { + "author": "Lawrence Chen", + "title": "cmux-next perf-tabs: capture after a chat list answer only for a New Tab page" + }, + { + "author": "Lawrence Chen", + "title": "cmux-next perf-tabs: review fixes for previews and the New Tab frame" + }, + { + "author": "Lawrence Chen", + "title": "cmux-next perf-tabs: page-tracked New Tab frame, paint hold on size change, versioned page previews" + }, + { + "author": "Lawrence Chen", + "title": "cmux-next perf-tabs: explicit self in the New Tab capture closure" + }, + { + "author": "Lawrence Chen", + "title": "cmux-next perf-tabs: New Tab frame review fixes" + }, + { + "author": "Lawrence Chen", + "title": "cmux-next perf-tabs: the New Tab frame never shows old chats or an old model" + }, + { + "author": "Lawrence Chen", + "title": "cmux-tui: conversation tab split tests import TreeDelta" + }, + { + "author": "Lawrence Chen", + "title": "cmux-tui: rustfmt and regenerated SDK bindings for conversation-tab-split-v1" + }, + { + "author": "Lawrence Chen", + "title": "cmux-tui: new-conversation-tab split makes the tab in a new pane in one pane-added delta (conversation-tab-split-v1)" + } + ], + "shortVersion": "1.0.0-nightly.3911131892801", + "summary": [ + { + "group": "new", + "title": "Carry explicit session lifecycle receipts" + }, + { + "group": "fixed", + "title": "Avoid duplicate base archive pathspec" + }, + { + "group": "fixed", + "title": "Release superseded space pager lock" + }, + { + "group": "fixed", + "title": "Refresh static verification inputs" + }, + { + "group": "fixed", + "title": "Fail closed for unsupported workspace name provenance" + }, + { + "group": "fixed", + "title": "Show focus rings only for keyboard navigation" + }, + { + "group": "changed", + "title": "Coalesce activity bridge state pushes" + }, + { + "group": "changed", + "title": "Release completed list motion animations" + } + ], + "version": 1, + "whatsNew": { + "channel": "nightly", + "date": "2026-10-18", + "entries": [ + { + "audience": "all", + "category": "new", + "docs": "https://cmux.com/docs/changelog", + "id": "summary-0", + "platforms": ["macos"], + "summary": { + "en": "Carry explicit session lifecycle receipts" + }, + "title": { + "en": "Carry explicit session lifecycle receipts" + } + }, + { + "audience": "all", + "category": "fixed", + "docs": "https://cmux.com/docs/changelog", + "id": "summary-1", + "platforms": ["macos"], + "summary": { + "en": "Avoid duplicate base archive pathspec" + }, + "title": { + "en": "Avoid duplicate base archive pathspec" + } + }, + { + "audience": "all", + "category": "fixed", + "docs": "https://cmux.com/docs/changelog", + "id": "summary-2", + "platforms": ["macos"], + "summary": { + "en": "Release superseded space pager lock" + }, + "title": { + "en": "Release superseded space pager lock" + } + }, + { + "audience": "all", + "category": "fixed", + "docs": "https://cmux.com/docs/changelog", + "id": "summary-3", + "platforms": ["macos"], + "summary": { + "en": "Refresh static verification inputs" + }, + "title": { + "en": "Refresh static verification inputs" + } + }, + { + "audience": "all", + "category": "fixed", + "docs": "https://cmux.com/docs/changelog", + "id": "summary-4", + "platforms": ["macos"], + "summary": { + "en": "Fail closed for unsupported workspace name provenance" + }, + "title": { + "en": "Fail closed for unsupported workspace name provenance" + } + }, + { + "audience": "all", + "category": "fixed", + "docs": "https://cmux.com/docs/changelog", + "id": "summary-5", + "platforms": ["macos"], + "summary": { + "en": "Show focus rings only for keyboard navigation" + }, + "title": { + "en": "Show focus rings only for keyboard navigation" + } + }, + { + "audience": "all", + "category": "improved", + "docs": "https://cmux.com/docs/changelog", + "id": "summary-6", + "platforms": ["macos"], + "summary": { + "en": "Coalesce activity bridge state pushes" + }, + "title": { + "en": "Coalesce activity bridge state pushes" + } + }, + { + "audience": "all", + "category": "improved", + "docs": "https://cmux.com/docs/changelog", + "id": "summary-7", + "platforms": ["macos"], + "summary": { + "en": "Release completed list motion animations" + }, + "title": { + "en": "Release completed list motion animations" + } + } + ], + "headline": { + "en": "Carry explicit session lifecycle receipts" + }, + "schemaVersion": 1, + "version": "1.0.0-nightly.3911131892801" + } + }, + { + "build": "3909307839101", + "changes": [], + "date": "2026-10-18", + "head": "b7eb4542b8a1b21e74678f10ddb9243326dcc5e7", + "highlights": [], + "items": [ + { + "author": "Lawrence Chen", + "title": "cmux-next: the focus machine is its own target, CmuxNextFocus (focus state view, events, effects, topology, FocusMachine over the cmux_focus_* C ABI; no AppKit, no app imports); CmuxNextApp shrinks under its size cap (cx-8w027.2)" + }, + { + "author": "Lawrence Chen", + "title": "cmux-next notifications: an unread mark on a viewed tab is read at once on every path (viewed-tab observation, re-armed by the settled focus; O(1) viewed-tab lookup) (cx-8w027.2)" + }, + { + "author": "Lawrence Chen", + "title": "cmux-next focus: compile fixes (replay entry shadowing, location trail content name) (cx-8w027.2)" + }, + { + "author": "Lawrence Chen", + "title": "cmux-next focus: review fixes: FocusState Codable for observations, view reads fields of an ok-0 reply, location-trail settle key includes active window, top page and workspace, replay window count, no topology per mount in apply's second sync (cx-8w027.2)" + }, + { + "author": "Lawrence Chen", + "title": "cmux-next focus: the window's FocusMachine owns the state (typed cmux_focus_* calls, no whole-state JSON), topology sent only when it changed, settle observers only on a new target with O(1) lookups (cx-8w027.2)" + }, + { + "author": "Lawrence Chen", + "title": "cmux NEXT settings: surfaces mix from the page background, clear over a see-through window" + }, + { + "author": "Lawrence Chen", + "title": "bench_pane_scale: status runs last (its tickers outlive it); per-tick layout counters (review) (cx-8w027.1)" + }, + { + "author": "Lawrence Chen", + "title": "bench_pane_scale: the tabs phase runs Next Tab (nextSurface; nextTab no longer exists, so the phase measured nothing); a status phase with OSC 7501 tickers (cx-8w027.1)" + }, + { + "author": "Lawrence Chen", + "title": "perf-switch: hibernation sync resolves a provisional page key (review) (cx-8w027.5)" + }, + { + "author": "Leo", + "pr": 21413, + "title": "test(next): target discover empty state selector" + }, + { + "author": "Lawrence Chen", + "title": "cmux-next: debug.themes reports a glass blend added this turn as its first keyframe (cx-8w027.3)" + }, + { + "author": "Lawrence Chen", + "title": "cmux-next: a subtree's first paint in a scope (root, adopt, overlay material) paints hidden views too; only theme changes wait for show (cx-8w027.3)" + }, + { + "author": "Lawrence Chen", + "title": "cmux-next: a hidden view skipped by passes from two scopes repaints the wider region when shown; drop the dead revision skip (review, cx-8w027.3)" + }, + { + "author": "Lawrence Chen", + "title": "cmux-next: hidden subtrees repaint when shown, not on every theme change (scope paint revision, one mark per hidden view); debug.themes reports the glass tint blend; color-transition-e2e --material glass checks the glass blend's first frames (I5, cx-8w027.3)" + }, + { + "author": "Lawrence Chen", + "title": "scripts: transparency-shots selects each new tab before its snapshot" + }, + { + "author": "Lawrence Chen", + "title": "perf-switch: agent page hibernation checks only the tabs a presentation change is about (cx-8w027.5)" + }, + { + "author": "Lawrence Chen", + "title": "scripts: transparency-shots.py, snapshots of every surface over a see-through window" + } + ], + "shortVersion": "1.0.0-nightly.3909307839101", + "summary": [ + { + "group": "changed", + "title": "An unread mark on a viewed tab is read at once on every path (viewed-tab observation,…" + }, + { + "group": "changed", + "title": "Compile fixes (replay entry shadowing, location trail content name)" + }, + { + "group": "changed", + "title": "Cmux NEXT settings: surfaces mix from the page background, clear over a see-through window" + }, + { + "group": "changed", + "title": "A subtree's first paint in a scope (root, adopt, overlay material) paints hidden views…" + }, + { + "group": "changed", + "title": "A hidden view skipped by passes from two scopes repaints the wider region when shown;…" + } + ], + "version": 1 + }, + { + "build": "3909161799401", + "changes": [], + "date": "2026-10-18", + "head": "b75ba897ad3854fbdb9896f7c1e34f008230d86f", + "highlights": [], + "items": [ + { + "author": "Lawrence Chen", + "title": "cmux-next: pin CCmuxAppFFI to cmux-app-ffi-cb72f89622ae (cmux_focus_* handle ABI; fixes the app FFI pin check after f6c4b05d0cb3) (cx-8w027.2)" + }, + { + "author": "Lawrence Chen", + "title": "cmux NEXT perf-observe: New Tab page ids observed per tab (cx-8w027.1.1)" + }, + { + "author": "Lawrence Chen", + "title": "perf-switch: BrowserHibernation comment names the one warm set (cx-8w027.5)" + }, + { + "author": "Lawrence Chen", + "title": "perf-switch: a window keeps every workspace it showed mounted; only GPU surfaces leave (cx-8w027.5)" + }, + { + "author": "Austin Wang", + "pr": 21365, + "title": "feat(cloud): read-only Huge Blue app-server inspection route" + }, + { + "author": "Leo", + "pr": 21404, + "title": "ci: keep PR review links concise" + } + ], + "shortVersion": "1.0.0-nightly.3909161799401", + "summary": [ + { + "group": "new", + "title": "Read-only Huge Blue app-server inspection route" + }, + { + "group": "changed", + "title": "Cmux NEXT perf-observe: New Tab page ids observed per tab" + } + ], + "version": 1 + }, + { + "build": "3908633532301", + "changes": [], + "date": "2026-10-18", + "head": "0b7075865f94b28225bea4d3cfde5d7e0b9622b1", + "highlights": [], + "items": [ + { + "author": "Leo", + "pr": 21386, + "title": "acpmux: fence mailbox identities by session receipts" + }, + { + "author": "Leo", + "pr": 21400, + "title": "ci: stop publishing internal gallery details to PRs" + } + ], + "shortVersion": "1.0.0-nightly.3908633532301", + "summary": [], + "version": 1 + }, + { + "build": "3908291645501", + "changes": [], + "date": "2026-10-18", + "head": "04810b5a38a4a4f079f2b3619457c45a5ea9cf40", + "highlights": [], + "items": [ + { + "author": "Leo", + "pr": 21359, + "title": "docs(cmux-next): define remote observation architecture" + }, + { + "author": "Leo", + "pr": 21316, + "title": "perf: reduce sidebar and list layout scans" + }, + { + "author": "Lawrence Chen", + "title": "ci: a script that macOS /bin/bash 3.2 cannot parse fails the nightly signing jobs" + }, + { + "author": "Leo", + "pr": 21339, + "title": "feat(cmux-next): refresh Apps discover home" + }, + { + "author": "Leo", + "pr": 21376, + "title": "perf(next): stabilize minimap tick callbacks" + } + ], + "shortVersion": "1.0.0-nightly.3908291645501", + "summary": [ + { + "group": "new", + "title": "Refresh Apps discover home" + }, + { + "group": "changed", + "title": "Reduce sidebar and list layout scans" + }, + { + "group": "changed", + "title": "Stabilize minimap tick callbacks" + } + ], + "version": 1 + }, + { + "build": "3908044538301", + "changes": [], + "date": "2026-10-18", + "head": "d7b11e8d1328d6a6221e8433cf181ee579da83a9", + "highlights": [], + "items": [ + { + "author": "Leo", + "pr": 21329, + "title": "perf(next): fade loaded reply images without layout work" + }, + { + "author": "Leo", + "pr": 21369, + "title": "perf(cmux-next): avoid duplicate older-history loads" + }, + { + "author": "Leo", + "pr": 21340, + "title": "test(cmux-next): cover Apps page browser flows" + }, + { + "author": "Austin Wang", + "pr": 21358, + "title": "cmux-next: show the default workspace-N name in new workspace rows" + } + ], + "shortVersion": "1.0.0-nightly.3908044538301", + "summary": [ + { + "group": "new", + "title": "Show the default workspace-N name in new workspace rows" + }, + { + "group": "changed", + "title": "Fade loaded reply images without layout work" + }, + { + "group": "changed", + "title": "Avoid duplicate older-history loads" + } + ], + "version": 1 + }, + { + "build": "3907660300601", + "changes": [], + "date": "2026-10-17", + "head": "bea8bebf8163d57e247f183b434169e460e0e9a5", + "highlights": [], + "items": [ + { + "author": "Leo", + "pr": 21324, + "title": "test(cmux-next): audit sidebar and workspace switch motion" + }, + { + "author": "Leo", + "pr": 21325, + "title": "fix(next): keep workspace list stable during switches" + }, + { + "author": "Leo", + "pr": 21326, + "title": "ci: preserve trusted dev-build artifacts on current base" + }, + { + "author": "Lawrence Chen", + "title": "Remove main files added under directories feat-cmux-next deleted (main sync 2026-10-17, cx-q1lnl)" + }, + { + "author": "Lawrence Chen", + "title": "cmux NEXT perf-observe: equal observations wake nobody; O(1) store index kept per change; keyed observable storage (cx-8w027.1)" + }, + { + "author": "Lawrence Chen", + "title": "perf-switch: a window record save reads no pane after a switch (cx-8w027.5)" + }, + { + "author": "Lawrence Chen", + "title": "cmux-next: ThemeRepaint runs responders after the hooks, records animated regions first, retains request owners, ends a runaway round without a blend; setParent defers root appearances (review, cx-8w027.3)" + }, + { + "author": "Lawrence Chen", + "title": "cmux-next: ThemeRepaint request roots as explicit closures (a [x] closure is a capture list) (cx-8w027.3)" + }, + { + "author": "Lawrence Chen", + "title": "cmux-next: theme repaints collect in one batch: record the colors on screen, then appearances, then each view's hook once, then blends (light/dark flips blend, a view in two regions runs once); page-host replay records the theme it sent (review, cx-8w027.3)" + }, + { + "author": "Lawrence Chen", + "title": "cmux-next: LayerColor nonisolated; OverlaySurface re-resolves its content through ThemeRepaint (cx-8w027.3)" + }, + { + "author": "Lawrence Chen", + "title": "cmux-next: ThemeRepaint blend opt-out through a weak layer set, not KVC (crash ratchet) (cx-8w027.3)" + }, + { + "author": "Lawrence Chen", + "title": "cmux-next: theme repaint without window capture: scope-region hook pass, render-server color blends from the shown value, glass tint set once, blur on change, page theme pushed only on change (I5, cx-8w027.3)" + }, + { + "author": "Lawrence Chen", + "title": "cmux-next perf-tabs: keep CmuxNextApp at its size cap" + }, + { + "author": "Lawrence Chen", + "title": "cmux-next perf-tabs: review fixes for eviction pictures and the browser host filter" + }, + { + "author": "Lawrence Chen", + "title": "perf-switch: shorter comments keep CmuxNextApp at its line cap (cx-8w027.5)" + }, + { + "author": "Lawrence Chen", + "title": "perf-switch: the surface invariant check is one deadline, debug builds only (cx-8w027.5)" + }, + { + "author": "Lawrence Chen", + "title": "perf-switch: a row click patches the selection too; no-viewport reveal resets (cx-8w027.5)" + }, + { + "author": "Lawrence Chen", + "title": "perf-switch: a workspace switch patches two sidebar rows and swaps in its own turn (cx-8w027.5)" + }, + { + "author": "Lawrence Chen", + "title": "cmux-next perf-tabs: return the switch expression in acceptsFirstResponder" + }, + { + "author": "Lawrence Chen", + "title": "cmux-next perf-tabs: the browser host refreshes only for browser tab changes" + }, + { + "author": "Lawrence Chen", + "title": "cmux-next perf-tabs: review fixes for the strip sync" + }, + { + "author": "Lawrence Chen", + "title": "cmux-next perf-tabs: no snapshots on a tab switch" + }, + { + "author": "Lawrence Chen", + "title": "cmux-next perf-tabs: park terminals in the pane, one strip sync per tab switch" + }, + { + "author": "Lawrence Chen", + "title": "cmux-focus-core: stateful focus handle C ABI (cmux_focus_*), in-place reducer, indexed topology, no-op responder and equal-topology fast paths (cx-8w027.2)" + }, + { + "author": "Leo", + "pr": 21337, + "title": "feat: add durable Freestyle runtime promotion slice" + }, + { + "author": "Leo", + "pr": 21330, + "title": "fix(cmux-next): reject stale deferred diff hydration" + }, + { + "author": "Lawrence Chen", + "title": "sidebar-instant-rows-live.py: the refused close runs last (its row's later jump in 2 of 4 runs is a follow-up)" + }, + { + "author": "Leo", + "pr": 21234, + "title": "feat(cmux-next): add priority agent sidebar projection" + }, + { + "author": "Lawrence Chen", + "title": "sidebar instant close: InstantClose type (WindowManager does not grow), WindowProfiles.shown, grace.rerunning; quiet stall prints WARN unless --strict-stall; app cap 113698 (from 113805)" + }, + { + "author": "Lawrence Chen", + "title": "cmux NEXT perf-layout: a terminal resizes and reports its grid once a drag stops; frame layout in TerminalHostView (cx-8w027.6)" + }, + { + "author": "Leo", + "pr": 21309, + "title": "fix: make merge freeze metadata auditable" + }, + { + "author": "Lawrence Chen", + "title": "check-app-size: lower the CmuxNextApp cap to 113690 (WorkspaceSlot moved out)" + }, + { + "author": "Lawrence Chen", + "title": "sidebar-instant-rows-live.py: quiet closes ask nothing between presses" + }, + { + "author": "Lawrence Chen", + "title": "sidebar-instant-rows-live.py: the stall check runs closes with no row sampling" + }, + { + "author": "Lawrence Chen", + "title": "sidebar-instant-rows-live.py: the trace ends on its time limit" + }, + { + "author": "Lawrence Chen", + "title": "sidebar instant close: review fixes" + }, + { + "author": "Lawrence Chen", + "title": "sidebar: instant workspace close, placeholder grace, name release at listing" + }, + { + "author": "Lawrence Chen", + "pr": 21319, + "title": "ci: notarize-nightly-dmg.sh parses under macOS /bin/bash 3.2 again" + }, + { + "author": "Leo", + "pr": 21247, + "title": "ci(cmux-next): add advisory visual evidence receipt" + }, + { + "author": "Leo", + "pr": 21308, + "title": "fix(cmux-next): guard stale session view state" + }, + { + "author": "Lawrence Chen", + "title": "cmux NEXT perf-layout: layout-changed carries the screen's layout (layout-delta-v1); the app patches one screen and its own drag echo does no work (cx-8w027.6)" + }, + { + "author": "Lawrence Chen", + "pr": 21311, + "title": "ci: export npm_config_prefix where create-dmg is installed for resumed DMGs" + }, + { + "author": "Lawrence Chen", + "title": "cmux-next tabs: TabStripView+HoverCards imports AppKit plainly (no public AppKit use left; cx-5jqsb)" + }, + { + "author": "Leo", + "pr": 21314, + "title": "ci(next): retain exact frame pacing receipts" + }, + { + "author": "Lawrence Chen", + "title": "cmux-next tabs: rename, overflow hint, closing-mode watch, edge fade, menu tracking, + hold, escape monitor and drag snapshot move out of TabStripView into owned helpers (2461 -> 2046 lines; cx-5jqsb)" + }, + { + "author": "Lawrence Chen", + "title": "cmux NEXT perf-layout: the applied-tree guard lives in CmuxNextBridge (CmuxNextApp size cap, cx-8w027.6)" + }, + { + "author": "Lawrence Chen", + "title": "cmux NEXT perf-layout: WorkspaceContentController equality guard within the CmuxNextApp size cap (cx-8w027.6)" + }, + { + "author": "Lawrence Chen", + "title": "cmux NEXT perf-layout: a root move re-syncs the overlay; one live style tracking at a time (review, cx-8w027.6)" + }, + { + "author": "Lawrence Chen", + "title": "cmux NEXT perf-layout: keep the second view sync (an equality check); the mount itself can move focus (cx-8w027.6)" + }, + { + "author": "Lawrence Chen", + "title": "cmux NEXT perf-layout: one overlay sync per frame, only changed screens reconcile, cached layout style, one motion policy per frame (cx-8w027.6)" + }, + { + "author": "Lawrence Chen", + "title": "cmux-next tabs: applyTokens stays in TabStripView.swift (it sets the private(set) metrics; cx-5jqsb)" + }, + { + "author": "Austin Wang", + "pr": 21178, + "title": "Fix Codex restore identity and recovery" + }, + { + "author": "Lawrence Chen", + "title": "cmux-next tabs: TabStripView's model and token observation move to TabStripView+Observation.swift (411 -> 348 lines; cx-5jqsb)" + }, + { + "author": "Austin Wang", + "pr": 21279, + "title": "test(cloud): cover activation past stale rollout cache" + }, + { + "author": "Austin Wang", + "pr": 20889, + "title": "Make Pro to Max upgrades work for every billing source" + }, + { + "author": "Lawrence Chen", + "title": "test: embed-cua-helper-dev builds its stub at the macOS 14 floor and proves a minos 15 helper fails the build (cx-sisy8)" + }, + { + "author": "Lawrence Chen", + "title": "sidebar: a creating row follows the live title rule (default names draw no title)" + }, + { + "author": "Lawrence Chen", + "title": "sidebar: debug row fields keep SidebarView's span" + }, + { + "author": "Lawrence Chen", + "title": "sidebar-instant-rows-live: closeTab takes no confirm; closes are proven by frames" + }, + { + "author": "Lawrence Chen", + "title": "sidebar: opensPage takes the enum's main actor" + }, + { + "author": "Lawrence Chen", + "title": "sidebar: creating rows match the first live row; review fixes" + }, + { + "author": "Lawrence Chen", + "title": "sidebar: debug.sidebar_rows reports row_state and directory; instant rows live proof" + }, + { + "author": "Lawrence Chen", + "title": "sidebar: a new workspace row is drawn final at the press" + }, + { + "author": "Leo", + "pr": 21297, + "title": "Fix shared webview baseline gates" + }, + { + "author": "Lawrence Chen", + "title": "cmux NEXT: Computer Use helper (dev) pin rebuilt for macOS 14; the embed refuses a helper that cannot load on the floor (cx-sisy8)" + }, + { + "author": "Leo", + "pr": 21303, + "title": "ci: enable managed gallery PR evidence on base" + }, + { + "author": "Lawrence Chen", + "title": "cmux NEXT: a shrinking pane lays out at its final frame when a split starts (no jump at rest)" + }, + { + "author": "Lawrence Chen", + "title": "devtools-device-mode-live: the T checks use the tagged app's own browser host (from its daemon socket), not the newest one on the Mac (cx-3ny35)" + }, + { + "author": "Austin Wang", + "pr": 20830, + "title": "Fix Claude Teams pane width and stale split recovery" + }, + { + "author": "Leo", + "pr": 21242, + "title": "cmux-next: add opt-in animation variant lab" + }, + { + "author": "Lawrence Chen", + "title": "devtools-device-mode-live: T checks: an agent click on a link and a button lands with device mode's iPhone preset on and after it ends (cx-3ny35)" + }, + { + "author": "Lawrence Chen", + "title": "cmux-browser-host: a press goes as touch when the page reports touch points (DevTools device mode turns touch on without telling the app); its moves and release follow (cx-3ny35)" + }, + { + "author": "Lawrence Chen", + "title": "test(cmux-browser-host): a page whose touch DevTools device mode turned on gets touch events (cx-3ny35, red)" + }, + { + "author": "Lawrence Chen", + "title": "settings export repair: review fixes (split Mac steps and verified flags, fail a failed regeneration, check-stamp, snapshot after any regeneration, export only on a stale stamp, route without guard-only paths, exporter file list guard)" + }, + { + "author": "Lawrence Chen", + "title": "cmux-next: below macOS 26, bind no-task task locals inside a synchronously started main-actor task (NEXT 3889579838401 crash on macOS 15.8.1)" + }, + { + "author": "Lawrence Chen", + "title": "os-smoke: a Cmd-T burst after Chromium loads (red: the New Tab hold's inline deinit traps on macOS 15.4 to 15.x)" + }, + { + "author": "Lawrence Chen", + "title": "settings exports repair themselves: generated-files regenerates a stale settings export (source stamp), base autofix copies it and the defaults snapshot (cx-kp9b4)" + }, + { + "author": "Lawrence Chen", + "title": "cmux-browser-host: rustfmt the touch test (cx-3ny35)" + }, + { + "author": "Lawrence Chen", + "title": "settings export stamp at 1c45ee27d046 from fleet export step b0c7b3e042985572288bd016 (exports unchanged)" + }, + { + "author": "github-actions[bot]", + "title": "chore(next): base autofix at 1c45ee27d046" + }, + { + "author": "Lawrence Chen", + "title": "settings export stamp from fleet export step b20e6a6361ee2351133c0c28 at 97e5c7658e2d (exports unchanged)" + }, + { + "author": "Lawrence Chen", + "pr": 21217, + "title": "ci: ship the app stapled inside the DMG (main, needs Lawrence)" + }, + { + "author": "Lawrence Chen", + "title": "settings export stamp: move to schemas/settings-export (schemas/settings is a web bundle input)" + }, + { + "author": "Lawrence Chen", + "title": "settings export stamp from fleet export step 7ad6abc533bf97443845611b at 1fd24c666bf0 (exports unchanged)" + }, + { + "author": "Lawrence Chen", + "title": "defaults_guard: stamp review fixes (missing stamp fails when the tree's exporter writes it; exact stamp bytes; cat-file header check)" + }, + { + "author": "Lawrence Chen", + "title": "settings export: source-digest stamp beside settings-schema.json; check-fresh fails when CmuxNextSettings moved without a re-export (cx-kp9b4)" + }, + { + "author": "Lawrence Chen", + "title": "cmux-next browser: a CEF tab records whether its emulation turned touch on and announces it to the browser host next to inputScale (cx-3ny35)" + }, + { + "author": "Lawrence Chen", + "title": "cmux-browser-host: a touch-emulating tab gets pointer input as Input.dispatchTouchEvent (touchStart/Move/End at the scaled point), mouse otherwise; the app announces touch next to inputScale (cx-3ny35)" + }, + { + "author": "Lawrence Chen", + "title": "test(cmux-browser-host): a touch-emulating tab gets touch events, mouse again after clear (cx-3ny35, red)" + }, + { + "author": "Leo", + "pr": 21199, + "title": "feat(agent-chat): add safe URL chip hover cards" + }, + { + "author": "Leo", + "pr": 21180, + "title": "Keep pasted HTML and JSX source editable in the composer" + }, + { + "author": "Lawrence Chen", + "title": "generated: settings schema and defaults snapshot from source on feat-cmux-next: ui.animations.newWorkspace default true (hq-4e's e190c402 carried a pre-merge false; cx-kp9b4)" + }, + { + "author": "Leo", + "pr": 21277, + "title": "fix(next): keep goal titles user-facing" + }, + { + "author": "Leo", + "pr": 21196, + "title": "ci: disable per-PR gallery workflow" + }, + { + "author": "Lawrence Chen", + "title": "cmux-tui dev profile: acpmux at opt-level 0 (edit rebuild 24.5 s -> 4.4 s, same test time)" + }, + { + "author": "Lawrence Chen", + "pr": 21276, + "title": "web: company email accounts are Team with no Cloud machine cap" + }, + { + "author": "Lawrence Chen", + "title": "generated: settings schema, MDM docs and defaults snapshot for ui.paneAnimations true" + }, + { + "author": "Leo", + "pr": 21265, + "title": "ci(web): shard webview test files" + }, + { + "author": "Leo", + "pr": 21250, + "title": "ci: paginate guard attribution commit pulls" + }, + { + "author": "Leo", + "pr": 21252, + "title": "fix(acpmux): normalize null mailbox metadata" + }, + { + "author": "Lawrence Chen", + "title": "cmux NEXT: pane animations on by default (ui.paneAnimations true)" + }, + { + "author": "Leo", + "pr": 21267, + "title": "fix(ci): accept guarded matrix conditions" + }, + { + "author": "Austin Wang", + "pr": 20849, + "title": "Fix Codex memory worker session ownership" + }, + { + "author": "Leo", + "pr": 21254, + "title": "feat(next): surface unresolved conversation goal" + }, + { + "author": "Leo", + "pr": 21237, + "title": "fix(acpmux): close remote mailbox authorization boundary" + }, + { + "author": "Lawrence Chen", + "title": "nextest priorities: 100-terminal tests keep the default; the 300-terminal test gets 240 s" + }, + { + "author": "Lawrence Chen", + "title": "cmux-tui nextest: start the slowest tests first (priorities)" + }, + { + "author": "Lawrence Chen", + "title": "cmux-tui-rust-check: prune debug/deps of a warm target to this build's units (491k stale files made every test process wait ~14 s in SecCodeCopySelf)" + }, + { + "author": "Leo", + "pr": 21266, + "title": "fix(ci): scope merged-head god-file audits" + }, + { + "author": "Austin Wang", + "pr": 20850, + "title": "Fix blank Codex surface after tab reparenting" + }, + { + "author": "Austin Wang", + "pr": 18442, + "title": "feat: opt in to trusted SSH OSC 52 clipboard writes" + }, + { + "author": "Lawrence Chen", + "title": "reload.sh: pass NX_REMOTE and ACPMUX_AGENT_LAUNCH to the tagged launch" + }, + { + "author": "Leo", + "pr": 21202, + "title": "ci(next): ratchet shared guard debt" + }, + { + "author": "Lawrence Chen", + "title": "brain warm: review fixes (never awaited by the wake's delivery; one per conversation, mux.wake items only; only an enabled pi Chief's brain warms its reads)" + }, + { + "author": "Austin Wang", + "pr": 20858, + "title": "ci: route high-volume bots through cmux-bot" + }, + { + "author": "Lawrence Chen", + "title": "cmux NEXT: a GUI job's app never asks for notification permission (NX_REMOTE=1, CMUX_TEST_REQUIRE_GUI=1)" + }, + { + "author": "lawrencecchen", + "title": "cmux-next: backdrop-art.json carries each work's focal point, tint, darkest and lightest colors (coordinator, for GPUI's tint and crop). export-backdrop-art.py reads them from BackdropArt+Entries.swift (generated from art/manifest.json): focal {x, y}, tint (preferred tint opacity), darkest/lightest as #RRGGBB. Red first: --check exited 1 on the old JSON after the generator change; 0 after regenerating" + }, + { + "author": "Lawrence Chen", + "title": "First-turn path: the conversation's outbox starts the woken Chief's brain (and its admission reads) beside MuxDO's wake commit" + }, + { + "author": "Lawrence Chen", + "title": "Chief hands on staging: hand tree 53de377a with the agent daemon pre-start and its image cmuxnp-stg-hand-v4; Mac hands on for hq-6d's Hands Settings proof (owners: Lawrence, the CMUX_UITEST account)" + }, + { + "author": "github-actions[bot]", + "title": "chore(next): base autofix at 90ab5ad7f994" + }, + { + "author": "Lawrence Chen", + "title": "devtools-device-mode-live: wait up to 240 s from launch for the CRLSet version folder (it installs in a later update round); not a known gap" + }, + { + "author": "Lawrence Chen", + "title": "devtools-device-mode-live: read the base page size once it holds (DevTools still moving to its remembered dock side made D_off_restores_page flaky)" + }, + { + "author": "Lawrence Chen", + "title": "devtools-device-mode-live: known gaps cx-22w3i (page 1-2 px short in rotate/responsive/zoom; CRLSet not installed within the run)" + }, + { + "author": "Lawrence Chen", + "title": "devtools-device-mode-live: the Widevine SD check plays the H.264 variant; page and DevTools frames recorded for rotate and responsive; CMUX_LIVE_EXTRA_SWITCHES for diagnosis" + }, + { + "author": "Lawrence Chen", + "title": "CEF device mode: the page keeps the device's full screen area (no cut to the pane, innerHeight matched Chrome's minus 2); live check: a working H.264/AAC sample, fast component updates with --widevine, installed version folders" + }, + { + "author": "Lawrence Chen", + "title": "devtools-device-mode-live: open the Chromium tab again after focusing the window when a fresh launch has no focused pane" + }, + { + "author": "Lawrence Chen", + "title": "CEF device mode: cmux's emulation and fit yield whenever DevTools device mode is on (also in a DevTools window), agent input scale and presented frame drop the fit's; live check samples the device width across the resize, waits for the page in the device area of its own tab, and requires CDM and CRLSet folders this run installed (review)" + }, + { + "author": "Lawrence Chen", + "title": "cmux-next: remote browser host linked against CEF cmux.28 (step 1b1bcf701600)" + }, + { + "author": "Lawrence Chen", + "title": "CEF: pin cef-154.0.28-cmux.28 (fork API 24: DevTools device mode, component updater paths for Widevine and CRLSet, H.264/AAC)" + }, + { + "author": "Lawrence Chen", + "title": "devtools-device-mode-live --require-widevine: H.264/AAC MP4 with sound, Widevine H.264 SD stream, CDM and CRLSet installed (cmux.28)" + }, + { + "author": "Lawrence Chen", + "title": "CEF: DevTools device mode places the page in the device's screen area (fork API 24, cx-fhcve)" + }, + { + "author": "Lawrence Chen", + "title": "webviews: vp fmt" + }, + { + "author": "Lawrence Chen", + "title": "webviews: one typed focus helper (focusWithRing) carries focusVisible for escapeFocus and the composer pickers; same behavior, typecheck green again" + }, + { + "author": "lawrencecchen", + "title": "ci: pull request trees publish Windows (daemon, host, acpmux) with completion-windows.json (chief 2026-10-17)" + }, + { + "author": "Lawrence Chen", + "title": "Chief hands continuation: its first message carries the made or found hand (id, name, online, work folder), so the model starts the agent at once" + }, + { + "author": "Lawrence Chen", + "title": "wake path: the commit-time wake drain never skips the alarm" + }, + { + "author": "Lawrence Chen", + "title": "cmux-next settings: regenerated settings schema after merging feat-cmux-next (cx-kp9b4)" + }, + { + "author": "Lawrence Chen", + "title": "base-red: cx-c0wvp pane-policy reds also need _acpmux/btw (ed2adf3d5591, #20826) in policy.json" + }, + { + "author": "Lawrence Chen", + "pr": 21255, + "title": "nightly: a refused nightly-next publication is an error and opens the failure issue" + }, + { + "author": "Lawrence Chen", + "title": "Channels view: format cloudHome.ts (vp fmt)" + }, + { + "author": "Lawrence Chen", + "title": "home-cloud-rows test: plain record compare (tsc)" + }, + { + "author": "Lawrence Chen", + "title": "rustfmt the corpus test" + }, + { + "author": "Lawrence Chen", + "title": "Channels view: Cloud rows follow the shared corpus (Chief name, peer id, timed mute)" + }, + { + "author": "Lawrence Chen", + "title": "One Cloud row corpus for the daemon's home-inbox and the Channels page (red: the page differs)" + }, + { + "author": "Lawrence Chen", + "title": "wake path: review fixes (one commit-time wake drain at a time per object, a commit during it looks again; pi warms only for an admitted wake; mux_at never after the wake)" + }, + { + "author": "Lawrence Chen", + "title": "First-turn path: a Chief's wake leaves the conversation at commit, not at the next alarm; the brain's wake reads the conversation beside its admission and warms the meter; admission reads the chief record and credits at the same time; mux_at mark" + }, + { + "author": "Lawrence Chen", + "title": "Chief hands: the fresh sign-in check reads the Stack session from the bearer token" + }, + { + "author": "Lawrence Chen", + "title": "test(cmux-next tabs): Shrink stops at Chrome's 32 / 56 then scrolls (cx-kp9b4)" + }, + { + "author": "Lawrence Chen", + "title": "generated: settings schema, MDM docs and defaults snapshot for ui.animations.newWorkspace true" + }, + { + "author": "Lawrence Chen", + "title": "cmux NEXT: panes equalize on close too, only an explicit equalize springs, new workspaces open on a spring by default" + }, + { + "author": "Lawrence Chen", + "title": "acpmux hand: a sandbox hand starts its agent daemon at hand start (the first agent.start took 2.0 s against 0.76 s warm)" + }, + { + "author": "Lawrence Chen", + "title": "sidebar undo: early undos run in the order asked; no pending step while an undo runs; echo check reports coarse samples (review of cx-kpicb, cx-8quut)" + }, + { + "author": "Lawrence Chen", + "title": "timing marks: review fixes (boot only for a wake that made the object; stale pending marks dropped at flush; reserved only when credits were held)" + }, + { + "author": "Lawrence Chen", + "title": "cmux-next settings: regenerated settings schema for Chrome's tab minimums (fleet export 3b7fdfae; cx-kp9b4)" + }, + { + "author": "Lawrence Chen", + "title": "Chief hands: presence-key review fixes (no rollback replay, no install key, race-safe write)" + }, + { + "author": "Lawrence Chen", + "title": "Chief brain timing: cold-start and gateway step marks (boot_at, life_at, reserved_at, upstream_at, headers_at); the wake awaits the lifecycle start" + }, + { + "author": "Lawrence Chen", + "title": "sidebar undo: the pending step goes through registerUndo (App size cap, no new App lines)" + }, + { + "author": "Lawrence Chen", + "title": "cmux-next tabs: Shrink minimums back to Chrome's 32 inactive / 56 selected from the shared tokens (Lawrence 2026-10-16: \"chrome 32\"; cx-kp9b4)" + }, + { + "author": "Lawrence Chen", + "pr": 13742, + "title": "Chief hands: replacing an install's presence key needs the current key or a fresh sign-in" + }, + { + "author": "Lawrence Chen", + "title": "test: SidebarSurfaceTests measure the default chrome style explicitly (the app default is flat-sidebar-line now)" + }, + { + "author": "Lawrence Chen", + "pr": 21243, + "title": "ci: 6 h stapled-app fallback ships the accepted first DMG" + }, + { + "author": "Lawrence Chen", + "title": "cmux-next tabs: the minimum-width hint needs room for itself and three minimum tabs, not 2.5 times its width, so a normal window shows it (nxdog108-v1 input proof, cx-kp9b4)" + }, + { + "author": "Lawrence Chen", + "title": "test(cmux-next tabs): the minimum-width hint shows in an 854 pt strip (an 1100 pt window), red on nxdog108-v1 (cx-kp9b4)" + }, + { + "author": "Lawrence Chen", + "title": "backend: compactor/memory review fixes: resume failure folds instead of stopping the object, append refolds when the core is ahead of the log, shared rate-limit backoff" + }, + { + "author": "Lawrence Chen", + "title": "optchat-wasm: rustfmt" + }, + { + "author": "Lawrence Chen", + "title": "backend: memory-load test: a Retry-After wait is also no longer than named (fails on the fixed 10 s)" + }, + { + "author": "Lawrence Chen", + "title": "backend: Cloud Chief compactor retries a rate limit with backoff; memory loads lazily from a checkpoint" + }, + { + "author": "Lawrence Chen", + "title": "backend: behavior test: a rate-limited compactor backs off (jitter, Retry-After); memory resumes from a checkpoint (red)" + }, + { + "author": "Lawrence Chen", + "title": "cmux-next tabs: pinned tabs stay fixed at the leading edge while the strip scrolls (cx-kp9b4)" + }, + { + "author": "Leo", + "pr": 21149, + "title": "feat(agent-chat): persist mailbox delivery receipts" + }, + { + "author": "Lawrence Chen", + "title": "Chief hands on staging: the hand from ee142801c3eb (tree a8f583ab) and the image that carries it (cmuxnp-stg-hand-v3, /root/proj)" + }, + { + "author": "Lawrence Chen", + "title": "generated: settings schema, MDM docs and defaults snapshot for the flat-sidebar-line default" + }, + { + "author": "Lawrence Chen", + "title": "cmux-next tabs: failing test, pinned tabs stay fixed while the strip scrolls (cx-kp9b4)" + }, + { + "author": "Lawrence Chen", + "pr": 21219, + "title": "ci: newest nightly-next promotion request wins the release-surface ack" + }, + { + "author": "Lawrence Chen", + "title": "cmux NEXT: flat with sidebar line is the default look, no pane lines, equalize springs at 120 Hz, no omnibar line" + }, + { + "author": "lawrencecchen", + "title": "cmux-next: export the backdrop art list to plans/cmux-next/backdrop-art.json (cmux2-0b, chief decision 4). scripts/cmux-next/export-backdrop-art.py reads the CmuxNextDesign Swift (BackdropArt ids and titles, BackdropArt+Entries, collections and retired ids, BackdropArt.dailyRotation, BackdropArtDownloads.remoteBase, AppleWallpapers) and writes ids, titles, artist/year/museum, collection, bundled, thumbnail and full image URLs (the cmux-art-publish hashes) with their bundled resources, source and license, the 4 collections, the Shuffle Daily list (173 of 174, no Goya's Saturn), retired ids, and the run-time macOS wallpaper/video sources (light/dark pairs and videos are not in the bundled catalog). --check runs in the cmux-next checks job (Backdrop art export): it fails when the JSON and the Swift differ" + }, + { + "author": "lawrencecchen", + "title": "cmux-daemon-client: DaemonConfig.raw_session_deltas (default off) reports each applied session.events delta as DaemonEvent::SessionDelta { revision, frame } just before its typed Delta, under one hold of the callback (cmux2-0b, chief decision 2). No wire or Cargo change; every DaemonConfig is built with DaemonConfig::new, so no construction site changes. Live test session_deltas_live (a new workspace: SessionDelta with the stream's delta, then Delta of the same revision; a client without the flag gets none), added to the cmux-tui-sdks live step. Red on base c89161a520a8: the test does not build (no field raw_session_deltas, no variant SessionDelta)" + }, + { + "author": "Leo", + "pr": 21235, + "title": "fix(agent-chat): respect reduced motion in history controls" + }, + { + "author": "Lawrence Chen", + "title": "run timing: review P3s (first output marked at block start, Step.ended_at in the contract, one clock read, one timing doc)" + }, + { + "author": "Lawrence Chen", + "title": "run timing test: a first answer that is a tool call only" + }, + { + "author": "Lawrence Chen", + "title": "Chief run timing: first_token_at is the run's first output (text, thinking or a tool call), continuation_at / continuation_first_token_at for the hands continuation; steps carry ended_at" + }, + { + "author": "Lawrence Chen", + "pr": 21220, + "title": "ci: newest nightly-next promotion request wins the release-surface ack (feat copy)" + }, + { + "author": "lawrencecchen", + "title": "cmux-tui: agent-browser provider keeps a response the peer wrote before it closed (hq-f8). read_control_line set SO_RCVTIMEO on every loop turn; on macOS setsockopt gives EINVAL after the peer closed, so buffered bytes were lost (control_response_limit_is_enforced_while_streaming failed about 1 in 10 on release builds). The timeout is now set once before the loop, EINVAL there means peer closed and reading continues, and each turn checks the deadline. Red first on the fleet Mac at 9ca4da0f6c5 (base b84401ae207): both new tests failed with os error 22, in the full run and alone" + }, + { + "author": "Lawrence Chen", + "title": "Chief hands: faster first sandbox and fewer failed first calls" + }, + { + "author": "lawrencecchen", + "title": "cmux-tui: red tests for the agent-browser provider read after the peer closed (hq-f8: macOS setsockopt SO_RCVTIMEO gives EINVAL after the peer closed, so buffered response bytes were lost)" + }, + { + "author": "Lawrence Chen", + "pr": 21216, + "title": "ci: nightly-sign.yml admits nightly runs from main in shadow mode (off by default)" + }, + { + "author": "Lawrence Chen", + "title": "sidebar drag spring starts when it is added; echo kinks measured per 120 Hz frame (cx-8quut)" + }, + { + "author": "Lawrence Chen", + "title": "sidebar: a drop never scrolls to reveal; only the drag's autoscroll moves the view (cx-8quut, hq-2d)" + }, + { + "author": "Lawrence Chen", + "title": "sidebar: a user's change puts its undo step and toast when it is sent; a Cmd-Z before the reply undoes it (cx-kpicb)" + }, + { + "author": "Lawrence Chen", + "title": "close-focus.md: V3/V5 sidebar reveal and anchor rule (chief approved, cx-ml98q)" + }, + { + "author": "Lawrence Chen", + "title": "sidebar-v2-drag-live: --only remove-undo focused rerun; undo evidence (cx-kpicb)" + } + ], + "shortVersion": "1.0.0-nightly.3907660300601", + "summary": [ + { + "group": "new", + "title": "Add durable Freestyle runtime promotion slice" + }, + { + "group": "new", + "title": "Add priority agent sidebar projection" + }, + { + "group": "new", + "title": "Add opt-in animation variant lab" + }, + { + "group": "fixed", + "title": "Keep workspace list stable during switches" + }, + { + "group": "fixed", + "title": "Reject stale deferred diff hydration" + }, + { + "group": "fixed", + "title": "Make merge freeze metadata auditable" + }, + { + "group": "changed", + "title": "Remove main files added under directories feat-cmux-next deleted" + }, + { + "group": "changed", + "title": "Cmux NEXT perf-observe: equal observations wake nobody; O(1) store index kept per…" + } + ], + "version": 1 + }, + { + "build": "3899481671301", + "changes": [], + "date": "2026-10-17", + "head": "99d6504ac77c5909b8e1b47f41f045f557c5510e", + "highlights": [], + "items": [ + { + "author": "Lawrence Chen", + "title": "cmux-next sidebar: bound the unsettled re-ask loop with for-in (check-concurrency base-red, cx-ml98q follow-up)" + }, + { + "author": "Lawrence Chen", + "title": "split + outcomes: review fixes (the fallback note text restored; rearm never loops on a past expiry or lifetime, direct alarm writes re-arm; revoke drops unsent outcomes; only pi opens beside the paid check; Run.timing step mark keys)" + }, + { + "author": "Leo", + "pr": 21176, + "title": "feat(agent-chat): fold older transcript turns" + }, + { + "author": "Lawrence Chen", + "title": "Cloud Chief: first-turn warmups and step marks, durable agent outcomes, brain-do.ts split" + }, + { + "author": "Lawrence Chen", + "title": "stale thinking strip: review fixes (never strip the open turn, log a mismatch there; comments on the fold and the Bedrock body)" + }, + { + "author": "Lawrence Chen", + "title": "Chief brain (P): drop thinking made under another tools list from each request (P0: the hands continuation replayed the first part's signed thinking -> 400)" + }, + { + "author": "Lawrence Chen", + "title": "late outcomes + shard: review fixes" + }, + { + "author": "Lawrence Chen", + "title": "Cloud Chief: late agent outcomes, sharded Claude turn counting and auth, parallel child starts, child cleanup" + }, + { + "author": "Lawrence Chen", + "title": "hands continuation: review fixes (timeout aborts the continuation too; messages steered during it are waited for; a list continues only when it found the first hand; the entry tool says the tools come right after the step; the test prefix only where ENVIRONMENT is test; the test checks the root turn's tools)" + }, + { + "author": "Lawrence Chen", + "title": "hands trim test: the list path also continues once in the same run" + }, + { + "author": "Lawrence Chen", + "title": "Chief brain (P): one message can make a sandbox and start an agent (one continuation in the same run with the full tools)" + }, + { + "author": "Lawrence Chen", + "title": "Chief hands: credential and key paths ask by rule, before the classifier model" + }, + { + "author": "Lawrence Chen", + "title": "hands trim fix: review P3s (SIGNED read from the newest text only; test docstring)" + }, + { + "author": "Lawrence Chen", + "title": "Chief brain (P): the hands tools change only at a turn boundary (P0: a mid-turn swap broke the next request with a signed-thinking 400)" + }, + { + "author": "Lawrence Chen", + "title": "chief-hands-trim: reproduce the signed-thinking 400 (the fake model binds thinking to the tools list like Anthropic)" + }, + { + "author": "Lawrence Chen", + "title": "Chief hands: the classifier prompt is a security review of a proposed action" + }, + { + "author": "Lawrence Chen", + "title": "Chief hands on staging: the published hand with the review fixes (tree ab2bf62f, source fee23b5b59f8)" + }, + { + "author": "Lawrence Chen", + "title": "acpmux hand: the person's default acpmux home comes from the config resolver (state roots)" + }, + { + "author": "Lawrence Chen", + "title": "Chief hands: review fixes for the agent approval path and the classifier" + }, + { + "author": "Lawrence Chen", + "title": "Chief hands: the classifier reads its verdict from any reply shape and names why when it cannot" + }, + { + "author": "Lawrence Chen", + "title": "Chief brain (P): the hand check leaves the turn's hot path (cached tool set, background refresh)" + }, + { + "author": "Lawrence Chen", + "title": "Chief hands on staging: Mac hands off again after the Mac test (HANDS_MAC_ENABLED unset, test owners and the classifier timeout removed)" + }, + { + "author": "Lawrence Chen", + "title": "chief-cache-live.py: warm turns must read >= 87% from the cache (hq-6d decision 2026-10-16: the live Home block stays after the cache mark; 90% waits on Lawrence) (cx-4a5w2)" + }, + { + "author": "Lawrence Chen", + "title": "Chief hands on staging: HAND_CLASSIFIER_TIMEOUT_MS=1 for the Mac test's classifier-timeout case (removed after the test)" + }, + { + "author": "Lawrence Chen", + "title": "Home debug socket: the texts answer stays one line (CmuxNextApp size cap) (cx-06vn1)" + }, + { + "author": "Lawrence Chen", + "title": "review fixes (cx-4a5w2): the Home rule keeps the focused-pane default and the empty-right case; chief-cache-live.py counts only its own turns and this run's transcripts" + }, + { + "author": "Lawrence Chen", + "title": "hands trim: review fixes (the entry tool waits for the tool swap before its result; turn start waits up to 1.5 s for it; chiefs profile limits checked before any write; entry name described; the test covers the entry path with a held turn and the next-turn path)" + }, + { + "author": "Lawrence Chen", + "title": "Home live run: the activity line keeps its row through the display frame that first shows the reply in the bubble's place and closes on the frame after it (cx-06vn1)" + }, + { + "author": "Lawrence Chen", + "title": "test(home): the real-turn proof fails when the activity line closes less than two display frames after the reply's hand-off was dispatched (the app records the display link fire of .streamEnd(replacedBy:) and of the line's close: lineCloseAfterHandOffFires) (cx-06vn1, red)" + }, + { + "author": "Lawrence Chen", + "title": "test(optchat-chief): the bare codex turn preset env also keeps only acpmux's cmux MCP server (cx-4a5w2)" + }, + { + "author": "Lawrence Chen", + "title": "Hands client: a Mac with no registered Cloud install says so on Allow and raise (21 locales), proof step 0 checks it (cx-om025)" + }, + { + "author": "Lawrence Chen", + "title": "optchat-chief: the Home workspace block's fixed text moves into the cached system prompt; the block after the cache mark holds only the ids, panes, tabs and screens (cx-4a5w2)" + }, + { + "author": "Lawrence Chen", + "title": "acpmux, optchat-chief: a Chief turn keeps only acpmux's cmux MCP server; computer use, secrets and session offers stay with subagents (cx-4a5w2)" + }, + { + "author": "Lawrence Chen", + "title": "hands trim test: only requests that carry a tool set" + }, + { + "author": "Lawrence Chen", + "title": "hands-client-live: turn the Cloud app server path on in a fleet (offline-backend) build, so the install key exists (cx-om025)" + }, + { + "author": "Lawrence Chen", + "title": "test(chief): a Chief turn gets only the cmux MCP server, and short warm turns in the tagged app read >= 90% from the cache (cx-4a5w2, red)" + }, + { + "author": "Lawrence Chen", + "title": "fake model: offered tools from the replayed system messages" + }, + { + "author": "Lawrence Chen", + "title": "hands trim test: one copy of the helpers" + }, + { + "author": "Lawrence Chen", + "title": "hands trim: behavior test (compact entry without a hand, full tools after pairing); the fake model records offered tools" + }, + { + "author": "Lawrence Chen", + "title": "Chief brain (P): compact hands entry until the Chief has a hand (-1.8k tokens/request); no length limits in the chiefs tool schema (-80)" + }, + { + "author": "Lawrence Chen", + "title": "hands-client-live: send a User-Agent (the API edge refuses urllib's, 403 error 1010) (cx-om025)" + }, + { + "author": "Lawrence Chen", + "title": "Hands client: staging behavior proof script; withdraw also removes queued banners (cx-om025)" + }, + { + "author": "Lawrence Chen", + "title": "wake delivery: type the send answer" + }, + { + "author": "Lawrence Chen", + "title": "wake delivery: review P2s (O ignores a resent wake at or below its cursor; wakes per conversation in seq order; 10 s limit per send, conversations in parallel in the alarm; give up after 6 h, not 12 tries; test also evicts after the brain took the wake)" + }, + { + "author": "Lawrence Chen", + "title": "wake delivery test: the local host acks with the Chief's install token; queue count from the owner's configure echo" + }, + { + "author": "Lawrence Chen", + "title": "wake delivery test: one copy of the helpers" + }, + { + "author": "Lawrence Chen", + "title": "MuxDO: at-least-once wake delivery to the Chief's own cloud brain (P0: an eviction during the wake RPC lost the wake)" + }, + { + "author": "Lawrence Chen", + "title": "Chief hands on staging: the CMUX_UITEST account (hq-6d Mac client proof) may use Mac hands and the Claude brain, with dogfood credits" + }, + { + "author": "Lawrence Chen", + "title": "Chief hands on staging: the hq-6d Mac client test user may use Mac hands (HANDS_MAC_OWNERS)" + }, + { + "author": "Lawrence Chen", + "title": "Hands client: crash-allow note for the presence prompt's unchecked Sendable (cx-om025)" + }, + { + "author": "Lawrence Chen", + "title": "Chief hands on staging: the published hand with approve-all at full and owner approvals for agent prompts (tree 53067f10, source 9fc30faae678)" + }, + { + "author": "Lawrence Chen", + "title": "Hands client: review fixes (cx-om025)" + }, + { + "author": "Lawrence Chen", + "title": "Mac app: Chief hands client: presence key, level raises with Touch ID, hand approvals in the approval banners (cx-om025)" + }, + { + "author": "Lawrence Chen", + "title": "chief fault hooks: review fixes (environment allowlist, session only, the Chief's own conversation, 200 only on the abort; the test faults a SLOW turn that runs and has not replied)" + }, + { + "author": "Lawrence Chen", + "title": "chief-fault test: evict once the turn exists (an eviction during the wake RPC loses the wake: reported, not covered)" + }, + { + "author": "Lawrence Chen", + "title": "Chief fault hooks (test-only): evict the pi brain or stop the opencode container in the middle of a turn" + }, + { + "author": "Lawrence Chen", + "title": "spawn: review fixes" + }, + { + "author": "Lawrence Chen", + "title": "acpmux hand: approve-all at level full, owner approval for agent prompts at auto/ask, idle stop" + }, + { + "author": "Lawrence Chen", + "title": "Cloud Chief: spawn(tasks[]) subagents with no hand" + }, + { + "author": "Lawrence Chen", + "title": "cmux-next Home: the debug branch probe never calls hostControl on the thread header (its assign menu is modal; it hung debug.home.drive in 1016-090855-f7f618) (cx-och3h)" + }, + { + "author": "Lawrence Chen", + "title": "cmux-next Home: tree threads round 2 review fixes and fast debug drives (cx-och3h)" + }, + { + "author": "Lawrence Chen", + "title": "route test: client message ids without spaces" + }, + { + "author": "Lawrence Chen", + "title": "MuxDO brain_impl is the one routing truth: GET/runs read it, PUT writes it first (review P2s), cached per object" + }, + { + "author": "Lawrence Chen", + "title": "MuxDO: route each Chief wake to its own brain by brain_impl (no await on the opencode brain for pi Chiefs)" + }, + { + "author": "Lawrence Chen", + "title": "pi prune review: count the rows deleted, no log line for a new brain, note on readers at an older point" + }, + { + "author": "Lawrence Chen", + "title": "prune test: a new stub after the object resets" + }, + { + "author": "Lawrence Chen", + "title": "pi prune: the agents SDK prefixes pi tables with pi_" + }, + { + "author": "Lawrence Chen", + "title": "Cloud Chief: guarded prune of pi-durable's old entries at each turn start (no running task or pending submission; entries before the newest head marker's range), behind CHIEF_BRAIN_PRUNE_PI (on in staging and tests, off in production)" + }, + { + "author": "Lawrence Chen", + "title": "steer review fixes: join only after pi has the turn's input (turnLive), the op is recorded before any await and stored for a restart (re-given to pi with the same id), a failed steer puts the rows back and keeps the ack range, only the turn's thread joins, a timeout aborts joined ops too" + }, + { + "author": "Lawrence Chen", + "title": "steer test doc; production config: why there is no deployment-wide daily total" + }, + { + "author": "Lawrence Chen", + "title": "Cloud Chief: a message that arrives while the conversation's turn runs joins that turn (pi steer after the current step), the turn waits for it, one reply" + }, + { + "author": "Lawrence Chen", + "title": "optchat-chief: set report_closed_ids: None in close_by_key (fix E0063 build break)" + }, + { + "author": "Lawrence Chen", + "title": "staging: paid-model turns 400 per owner per day, 3000 for the deployment (per-owner counting from 3408ed4dd991; worst case about 120 USD/day inside the chatmux caps)" + }, + { + "author": "Lawrence Chen", + "title": "cmux-next Home: thread header, Copy Link and old permalinks in native Home (cx-och3h)" + }, + { + "author": "Lawrence Chen", + "title": "cmux-next Home: red behavior check for the thread header, Copy Link and old permalinks in native Home (cx-och3h)" + }, + { + "author": "Lawrence Chen", + "title": "item 2 review: one daily-cap notice per conversation per day (marker in the brain object), old day counters deleted, env doc" + }, + { + "author": "Lawrence Chen", + "title": "item 2: notices wait out the loop guard (agent_rate) twice at most; claude test: a failed sign-in refuses the paid turn with one notice" + }, + { + "author": "Lawrence Chen", + "title": "Cloud Chief: paid-model daily limit per owner (CHIEF_BRAIN_CLAUDE_DAILY_TURNS; deployment cap only via _TOTAL), a paid Chief never falls back to an unmetered model, one notice per conversation per day when the limit is reached" + }, + { + "author": "Lawrence Chen", + "title": "nowait review: a turn with no frozen view yet may wait (3 s) for summaries; foldDue is a high-only heuristic" + }, + { + "author": "Lawrence Chen", + "title": "nowait test: the fake compactor hangs on HANG_COMPACT steps" + }, + { + "author": "Lawrence Chen", + "title": "nowait test: a small view budget so every turn's view needs a fold" + }, + { + "author": "Lawrence Chen", + "title": "nowait test: a hanging compactor (as the rate-limited one), fake holdCompacts" + }, + { + "author": "Lawrence Chen", + "title": "Cloud Chief: a turn never waits on the compactor (it runs on the frozen view + delta); only a forced re-render past the 32 KB growth cap waits, at most 3 s" + }, + { + "author": "Lawrence Chen", + "title": "Home debug texts: the stream and rebuild fields add no App lines (app-size cap) (cx-kmak2)" + }, + { + "author": "lawrencecchen", + "title": "cmux-tui: the public topology close value moves to resource_router/close_value.rs (no behavior change)" + }, + { + "author": "Lawrence Chen", + "title": "Chief hands on staging: the published hand with levels and the Mac classifier rules (tree 97c60d88)" + }, + { + "author": "Lawrence Chen", + "title": "acpmux hand: name the hand's own folders from their resolvers (check-state-roots)" + }, + { + "author": "Lawrence Chen", + "pr": 21215, + "title": "ci: ship cmux NEXT with the app stapled inside the DMG" + }, + { + "author": "Lawrence Chen", + "title": "ci: cmux NIGHTLY-identity split review fixes" + }, + { + "author": "Lawrence Chen", + "title": "ci: split publish-nightly-identity-legacy into sign, verify and publish" + }, + { + "author": "Lawrence Chen", + "title": "ci: tests for the cmux NIGHTLY-identity sign, verify and publish split" + }, + { + "author": "github-actions[bot]", + "title": "chore(next): base autofix at 849cfc8843d7" + }, + { + "author": "lawrencecchen", + "title": "cmux-tui: closed.list does not name workspace_key (the resource API boundary forbids registry keys as public fields)" + }, + { + "author": "lawrencecchen", + "title": "cmux-tui: closes name the closed groups they stored (closed_ids), closed.list members name workspace_key" + }, + { + "author": "Lawrence Chen", + "title": "devtools-device-mode-live: Chrome's base page size is read while its DevTools still opens; compare device fields only" + }, + { + "author": "Lawrence Chen", + "title": "browser.md: DevTools device mode parity and Widevine status (cx-fhcve, cx-sbe3h)" + }, + { + "author": "Lawrence Chen", + "title": "devtools-device-mode-live: a harness error, a missing Chrome or an unread log fails the run; CEFRuntime keeps an outer call's synchronous results (review)" + }, + { + "author": "Lawrence Chen", + "pr": 21212, + "title": "nightly: one nightly-next writer, NIGHTLY_NEXT_WRITER (mac, linux, none) (cx-f76kf)" + }, + { + "author": "Lawrence Chen", + "title": "CEFRuntime: keep DevTools results Chromium sends during ExecuteDevToolsMethod" + }, + { + "author": "Lawrence Chen", + "title": "cmux-next: live check for DevTools device mode against Google Chrome, emulation timing and Widevine status" + }, + { + "author": "Lawrence Chen", + "title": "cmux-next Home: tree threads keep CmuxNextApp at its size cap: the link parser moves to CmuxNextHome (HomeDockSelection(link:)), the debug helpers fold into DebugHomeNativeFixture (cx-och3h)" + }, + { + "author": "Lawrence Chen", + "title": "ci: pr-red-checks-comment runs on the Linux runner variable with the fork branch" + }, + { + "author": "Lawrence Chen", + "title": "ci: allow the macOS 15 fork branch for nightly-next-macos15-launch" + }, + { + "author": "Lawrence Chen", + "title": "cmux-next Home: a user thread action ends a waiting permalink through ChatIntents (main actor) (cx-och3h)" + }, + { + "author": "Lawrence Chen", + "title": "cmux-tui-core: drop the trailing blank line the main sync left in terminal_directory.rs (rustfmt, cx-q1lnl)" + }, + { + "author": "Lawrence Chen", + "title": "Home stream glue: review fixes (cx-kmak2)" + }, + { + "author": "Lawrence Chen", + "title": "cmux-next Home: tree threads review fixes (cx-och3h)" + }, + { + "author": "Lawrence Chen", + "title": "Chief hands: approval events on the owner's wire (hand-approval-pending, hand-approval-settled)" + }, + { + "author": "Lawrence Chen", + "title": "cmux-next Home: debug.home.drive thread and escape answer with the tree state (cx-och3h)" + }, + { + "author": "Lawrence Chen", + "title": "backend workerd tests: fix the slow parts of three cases, a measured 20 s suite timeout and a slow-tests report (cx-ek18n, cx-tr24n, cx-op9ik, cx-whzlv)" + }, + { + "author": "Lawrence Chen", + "pr": 21211, + "title": "nightly: read NIGHTLY_NEXT_HOLD live before the first nightly-next write (cx-f76kf)" + }, + { + "author": "Lawrence Chen", + "title": "Chief hands: owner approvals need the app proof to allow, raises need a presence key, provider stubs, the hands doc" + }, + { + "author": "Lawrence Chen", + "title": "new tab, settings: comments follow the new defaults; the gallery covers AppIllustration (review)" + }, + { + "author": "Lawrence Chen", + "title": "Home: the Chief's running reply is MessagesLab's streaming bubble (ask 11); the posted reply takes its place with .streamEnd(replacedBy:) (cx-kmak2)" + }, + { + "author": "Lawrence Chen", + "title": "test(home): the Chief's reply takes the bubble's place with no whole-window rebuild and no stream left (cx-kmak2, red)" + }, + { + "author": "Lawrence Chen", + "title": "cmux-next Home: vendor MessagesLab pin d7b2df6 (main 537f76e): a293970 + ask 11, the streaming typing bubble (cx-kmak2)" + }, + { + "author": "Lawrence Chen", + "title": "cmux-next Home: tree threads follow-up: TopHomePageView.show(_:message:) in the class body; the check turns Channels on in its own config file (cx-och3h)" + }, + { + "author": "Lawrence Chen", + "title": "settings: drop the unused raw --polish-shadow, the row range test covers the one look" + }, + { + "author": "Lawrence Chen", + "title": "Chief hands, levels: review fixes" + }, + { + "author": "Lawrence Chen", + "title": "cmux-next Home: nested threads in native Home (MessagesLab tree mode) (cx-och3h)" + }, + { + "author": "Lawrence Chen", + "title": "cmux-next Home: red behavior check for nested threads in native Home (cx-och3h)" + }, + { + "author": "Lawrence Chen", + "title": "type scale: lower the baseline after the old Settings theme preview and dense look went away" + }, + { + "author": "Lawrence Chen", + "title": "settings: the refined look is the default and only Settings look" + }, + { + "author": "Lawrence Chen", + "title": "new tab: the Cursor top strip is the default New Tab look, Fitted removed" + }, + { + "author": "Lawrence Chen", + "title": "Chief hands: permission levels (full, auto, ask, read-only), zero approvals in sandboxes, sandbox provider interface" + }, + { + "author": "Lawrence Chen", + "title": "optchat-chief review fixes: when the cmux app had not answered at host start, each turn start lists the tools again (a private pending marker) and denies the app's action tools once they appear; the tool-list child is killed and reaped by its handle, never by pid; agents_snapshot stays, so the Chief can find the ids its tools take (cx-68uof)" + }, + { + "author": "Lawrence Chen", + "title": "Remove main files added under directories feat-cmux-next deleted (main sync 2026-10-16 part 2, cx-q1lnl)" + }, + { + "author": "Lawrence Chen", + "title": "cmux-next: macOS 14 floor guard for every bundled Mach-O, release-build os-smoke, macOS 15 launch of the published DMG" + }, + { + "author": "Lawrence Chen", + "title": "backend file size: 1000 lines or 64 KB, whichever comes first (hq-1f decision)" + }, + { + "author": "Lawrence Chen", + "title": "optchat-chief: the count of a turn's new entries is taken under the turn_input lock (Chat::turn_input takes first_new), so an entry logged between the two reads cannot shift new_from (P2 from hq-1f, cx-68uof)" + }, + { + "author": "Lawrence Chen", + "title": "optchat-chief: the Chief allowlist names real cmux MCP tools (agents_*, render, app_show_pane, app_show_tab, app_tab_new_page, app_file_open); chiefs, conversations and memory are the optchat server's (cx-68uof)" + }, + { + "author": "Lawrence Chen", + "pr": 21173, + "title": "ci: the promote guard reads the whole range from the compare API" + }, + { + "author": "Lawrence Chen", + "title": "link-routing-live: type into the palette (debug.key target palette) and check its ranking" + }, + { + "author": "Lawrence Chen", + "title": "Remove main files added under directories feat-cmux-next deleted (main sync 2026-10-16, cx-q1lnl)" + }, + { + "author": "Lawrence Chen", + "title": "link-routing-live: run the link palette actions as the person does (a script run is refused)" + }, + { + "author": "Leo", + "pr": 21166, + "title": "ci: prepare trusted nightly-next pool rescue on main" + }, + { + "author": "Lawrence Chen", + "title": "generated: settings schema, MDM manifests, action surfaces, defaults snapshot and settings page strings for cx-ir3z4" + }, + { + "author": "Lawrence Chen", + "title": "optchat-chief: Chief turns load only 21 cmux MCP tools (conversations, Chiefs, workspaces and panes, agents); the others are denied in the turn settings from the CLI's own list (cmux --json mcp tools) and stay in the cmux CLI (cx-68uof)" + }, + { + "author": "Lawrence Chen", + "title": "agent pane: public import for the DEBUG link opener's signature" + }, + { + "author": "Austin Wang", + "pr": 21129, + "title": "Fix iOS cmux-tui topology reconnect (#21001)" + }, + { + "author": "Lawrence Chen", + "title": "updater: the update sheet's link opener default without a default-argument reference" + }, + { + "author": "Lawrence Chen", + "title": "scripts: link-routing-live.py, the GUI proof of cx-ir3z4 link routing" + }, + { + "author": "Lawrence Chen", + "title": "links: route every surface through LinkRouter; link and path menus; palette actions" + }, + { + "author": "Austin Wang", + "pr": 20944, + "title": "Fix Cloud workspace pane bounds after materialization" + }, + { + "author": "Austin Wang", + "pr": 20404, + "title": "fix(ci): handle Testbox cleanup cancellation during bound startup" + }, + { + "author": "Lawrence Chen", + "title": "settings: a free-text setting kind (text) in the Rust schema reader and the React settings page" + }, + { + "author": "Lawrence Chen", + "title": "wip(cx-ir3z4): link routing, settings and agent pane wiring (in progress)" + }, + { + "author": "Austin Wang", + "pr": 20346, + "title": "Keep Claude background subagents running after parent stop" + }, + { + "author": "Lawrence Chen", + "pr": 21151, + "title": "ci: the real signing import test carries the Developer ID G2 intermediate" + }, + { + "author": "Austin Wang", + "pr": 21128, + "title": "Fix Cmd+V image paste in forced-TTY SSH tmux sessions" + }, + { + "author": "Lawrence Chen", + "pr": 21049, + "title": "ci: promote guard for nightly-next" + }, + { + "author": "Lawrence Chen", + "pr": 21145, + "title": "ci: accept a Developer ID intermediate that the signing .p12 already added" + }, + { + "author": "Austin Wang", + "pr": 20570, + "title": "Keep a Cloud terminal's cwd: parse kitty-shell-cwd and publish early reports" + }, + { + "author": "Lawrence Chen", + "pr": 21135, + "title": "ci: extend agent-inbox-quick-view flag reviewBy to 2026-11-12" + }, + { + "author": "Lawrence Chen", + "pr": 21142, + "title": "ci: real macOS import test for the signing keychain tool" + }, + { + "author": "Lawrence Chen", + "pr": 21024, + "title": "ci: run app checks in secret-free jobs for the nightly path" + }, + { + "author": "Lawrence Chen", + "pr": 21140, + "title": "release, nightly: resume a complete staged release; nightly publishes by id (stacked on #21137)" + }, + { + "author": "Lawrence Chen", + "pr": 21043, + "title": "ci: import the signing certificate as a named .p12" + }, + { + "author": "Lawrence Chen", + "pr": 18380, + "title": "Harden cmux browser repl security boundaries" + }, + { + "author": "Austin Wang", + "pr": 20354, + "title": "Fix custom right-sidebar groups context" + }, + { + "author": "Austin Wang", + "pr": 20347, + "title": "fix: avoid duplicating restored zsh prompts" + }, + { + "author": "Lucas Ribeiro", + "title": "new tab: fitted and cursor values of the composer top strip switch" + }, + { + "author": "Lucas Ribeiro", + "title": "test: fitted and cursor new tab values of the top strip switch" + }, + { + "author": "Austin Wang", + "pr": 18641, + "title": "Fix iOS terminal sizing priority across background resume" + }, + { + "author": "Lucas Ribeiro", + "title": "settings: refined look keeps the sidebar icons' own stroke width" + }, + { + "author": "Lucas Ribeiro", + "title": "settings: keep the shipped look when the refined switch is off, visible button hover in the refined look" + }, + { + "author": "Lucas Ribeiro", + "title": "settings: refined look behind a debug switch (default off)" + }, + { + "author": "Lucas Ribeiro", + "title": "settings: cover default look and live refined switch" + } + ], + "shortVersion": "1.0.0-nightly.3899481671301", + "summary": [ + { + "group": "new", + "title": "Fold older transcript turns" + }, + { + "group": "new", + "title": "New tab: the Cursor top strip is the default New Tab look, Fitted removed" + }, + { + "group": "new", + "title": "New tab: fitted and cursor values of the composer top strip switch" + }, + { + "group": "fixed", + "title": "Fix Cloud workspace pane bounds after materialization" + }, + { + "group": "fixed", + "title": "Keep Claude background subagents running after parent stop" + }, + { + "group": "fixed", + "title": "Fix Cmd+V image paste in forced-TTY SSH tmux sessions" + }, + { + "group": "changed", + "title": "Bound the unsettled re-ask loop with for-in" + }, + { + "group": "changed", + "title": "Stale thinking strip: review fixes (never strip the open turn, log a mismatch there;…" + } + ], + "version": 1 + }, + { + "build": "3889579838401", + "changes": [], + "date": "2026-10-16", + "head": "7ceadc6175ce18edb4c891370f0e09543f2e7ade", + "highlights": [], + "items": [ + { + "author": "Leo", + "pr": 21182, + "title": "feat(acpmux): durable inter-session mailbox" + }, + { + "author": "Lawrence Chen", + "title": "Home pin a293970 (review): a thread path open clears the in-view send mark as reply/close do; README names the file pins, Home's .setNotice live line and the tree-mode glue still to do (cx-qor71)" + }, + { + "author": "Lawrence Chen", + "title": "cmux-next Home: vendor MessagesLab pin a293970 (main 6d6497c): width-model2 + host-hooks-b (cx-qor71)" + } + ], + "shortVersion": "1.0.0-nightly.3889579838401", + "summary": [ + { + "group": "new", + "title": "Durable inter-session mailbox" + } + ], + "version": 1 + }, + { + "build": "3889441310601", + "changes": [], + "date": "2026-10-16", + "head": "2059f8393b5a8b69794b30246fb01b46b56b815b", + "highlights": [], + "items": [ + { + "author": "Lawrence Chen", + "pr": 21170, + "title": "nightly: refuse recovery or publication of a build off the served lineage" + }, + { + "author": "Lawrence Chen", + "title": "Chief hands: hand-do.ts back under 500 lines (the verdict log is its own file)" + }, + { + "author": "Leo", + "pr": 21179, + "title": "ci: reuse attested nightly acpmux companions" + }, + { + "author": "Leo", + "pr": 21167, + "title": "ci: retain NEXT Release builds on a trusted nightly worker" + }, + { + "author": "Leo", + "pr": 21168, + "title": "ci: add exact-run SwiftPM test product transport" + }, + { + "author": "Leo", + "pr": 21165, + "title": "ci: measure cmux-next SwiftPM test builds" + }, + { + "author": "Lawrence Chen", + "title": "Cloud Chief prompt: the three note forms and that a note's target is a message id (hq-6d review P3)" + }, + { + "author": "Leo", + "pr": 21164, + "title": "ci: prevent older own nightly-next builds from replacing newer feeds" + }, + { + "author": "Lawrence Chen", + "title": "backend chief-brain-chiefs test: settle only until the chief is bound (one alarm per missing step), and a measured 20 s per case (0.5 s alone, 4.5 s in the full parallel suite)" + }, + { + "author": "Leo", + "pr": 21163, + "title": "ci: retain cmux-next Release compilation between owned-worker jobs" + }, + { + "author": "Lawrence Chen", + "title": "Chief hands, Mac classifier: review-3 fix; a scoped Mac test switch on staging" + }, + { + "author": "github-actions[bot]", + "title": "chore(next): base autofix at feea14159610" + }, + { + "author": "Lawrence Chen", + "title": "OptChat 5a core review fixes (51fc2006f482 review): forced block starts kept in Frozen.starts (a non-new user entry before the new messages no longer merges a sent block), imported messages never delta lines, a turn's own new messages do not count toward a re-render; Cloud wasm rebuilt with cuts + starts" + }, + { + "author": "Lawrence Chen", + "title": "Chief hands, Mac classifier: re-review fixes (3 P1)" + }, + { + "author": "Leo", + "pr": 21156, + "title": "ci: retain cmux-next Swift test builds between jobs" + }, + { + "author": "Leo", + "pr": 21161, + "title": "ci: resume saved unsigned nightly-next builds without recompiling" + }, + { + "author": "Lawrence Chen", + "title": "sidebar mirror: typed FFI reads (no main-actor JSON decode), app FFI pin cmux-app-ffi-9d01404fc7ab, main-actor baseline 0 for SidebarMirror.swift (cx-x5jpp)" + }, + { + "author": "Lawrence Chen", + "title": "sidebar-mirror-rebuild-perf.py: a refused close is recorded, not fatal (cx-x5jpp)" + }, + { + "author": "Lawrence Chen", + "title": "first-turn cost guard review fixes: tools loaded by a tool_reference count in the estimate, mcp_servers fails with no safe estimate, a 10 s count timeout when the route is not ready, an unreadable error body still warns, the real=1 limit says it is a per-request average, the fallback test runs in cmux-next CI (cx-68uof)" + }, + { + "author": "Lawrence Chen", + "title": "first-turn cost guard: a failed count_tokens (the team subrouter answers 502) falls back to ceil(request JSON bytes without deferred tools / 3.2) with a WARNING line and still fails over the limit; the stand-in run no longer needs the route; real=1 checks the first turn's provider usage against the limit (cx-68uof)" + }, + { + "author": "Lawrence Chen", + "title": "first-turn cost guard: red: a router that answers count_tokens with 502 makes the guard exit 4 instead of estimating (cx-68uof)" + }, + { + "author": "Lawrence Chen", + "title": "sidebar-mirror-rebuild-perf.py: read the workspace id from the create reply's value (cx-x5jpp)" + }, + { + "author": "Lawrence Chen", + "title": "Cloud Chief: a failed run names the model route's error in Run.error, and the Chief posts one short notice (no silent failure)" + }, + { + "author": "Lawrence Chen", + "title": "sidebar: a failed load while changes wait unanswered asks again, bounded (review of cx-ml98q)" + }, + { + "author": "Lawrence Chen", + "title": "sidebar-v2-drag-live: the moved active row may be unrealized off screen (cx-ml98q)" + }, + { + "author": "Lawrence Chen", + "title": "sidebar: unanswered changes settle at the next document load (review of cx-ml98q)" + }, + { + "author": "Lawrence Chen", + "title": "staging: stop sending thinking display + effort on the session route (no thought deltas came back; keep the proven body while Bedrock throttles)" + }, + { + "author": "Lawrence Chen", + "title": "Chief hands, Mac classifier: review fixes (2 P0, 4 P1, P2s)" + }, + { + "author": "Leo", + "pr": 21155, + "title": "ci: run exact Release admission for nightly control fixes" + }, + { + "author": "Lawrence Chen", + "title": "OptChat 5a: request-end cuts in optchat-core Frozen (a block once sent stays byte for byte, also wasm), a mark on the previous request's end (Bedrock has no look-back; the header mark only after a new view), subagent view lines keep their ids, inspector note says images follow the delta (cx-d7a4d)" + }, + { + "author": "Lawrence Chen", + "title": "sidebar-mirror-rebuild-perf.py: launch and stop $NX_APP inside an nx-remote job (cx-x5jpp)" + }, + { + "author": "Lawrence Chen", + "title": "Production Cloud Chief approvals for G7 from Lawrence's 2026-10-15 decisions (Opus 5.5 low default, chatmux service key, the 4 manaflow personal teams, credits enforced by code, 5 USD agent-token cap); service key a required secret (G5); staging sends thinking display + effort to test first token" + }, + { + "author": "Lawrence Chen", + "title": "sidebar perf: mirror_ns counter (main-thread time in SidebarMirror rows/acceptance) and sidebar-mirror-rebuild-perf.py (cx-x5jpp)" + }, + { + "author": "Lawrence Chen", + "title": "optchat-chief: red: a user entry right after a turn's messages joins that turn's last delta block, so the next turn's input no longer starts with the last one (spec 5a.2, cx-d7a4d)" + }, + { + "author": "Lawrence Chen", + "title": "sidebar: an unanswered drop stays pending and asks again; reveal only for the user's own move (cx-ml98q)" + }, + { + "author": "Leo", + "pr": 21020, + "title": "webviews: gallery reads Swift backslashes in WebTheme.bootstrapScript (base red)" + }, + { + "author": "Lawrence Chen", + "title": "sidebar mirror FFI: typed replies (rows, acceptance table, call status) with one interned string table (cx-x5jpp)" + }, + { + "author": "Lawrence Chen", + "title": "Chief hands: the Mac auto-mode classifier (off until tested), hand hard denies, the sandbox VM sweep" + }, + { + "author": "Lawrence Chen", + "title": "sidebar mirror: nonisolated deinit (main-thread concurrency check, cx-t7hu)" + }, + { + "author": "Leo Li", + "title": "ci: compile only the architectures shipped by each nightly" + }, + { + "author": "Leo Li", + "title": "test(ci): reproduce unused Intel builds in arm64 nightlies" + }, + { + "author": "Lawrence Chen", + "title": "sidebar-v2 client: landing note (known issues cx-ml98q, cx-x5jpp)" + }, + { + "author": "Lawrence Chen", + "title": "main-actor baseline: SidebarMirror.swift JSON decode 0 -> 3 (chief-approved raise, removal bead cx-x5jpp, expires 2026-10-20)" + }, + { + "author": "Lawrence Chen", + "title": "OptChat 5a on Bedrock: mark the previous turn's end (no look-back on Bedrock), so a turn reads all of the last turn's input" + }, + { + "author": "Lawrence Chen", + "pr": 21144, + "title": "nightly: run publication tooling from the workflow commit, not the recovered build" + }, + { + "author": "Lawrence Chen", + "title": "sidebar-v2 bridge: decode the sidebar document wire values off the main actor (main-actor work ratchet)" + }, + { + "author": "lawrencecchen", + "title": "cmux-agent-pane-policy: the acpmux environment on Windows (cx-flj2z, cx-ncc.54)" + }, + { + "author": "Lawrence Chen", + "title": "OptChat 5a review fixes: images go after the delta's end, an edit or retraction of a queued message updates or drops it, a skipped entry at a cut still ends the block, only entries before the turn's new messages count toward a re-render, unbuilt lines go to the delta (a frozen view never shows the placeholder), a logged steer stays in the delta, the traced end is the sent end (cx-d7a4d)" + }, + { + "author": "Lawrence Chen", + "title": "sidebar-v2 client: landing note (known issue cx-ml98q)" + }, + { + "author": "Lawrence Chen", + "title": "OptChat 5a: cache-stable turn input in optchat-core turn_input (frozen view, append-only delta, re-render rules); optchat-chief stores the frozen record, logs edits and retractions as notes naming the line, marks the header, the view's end and the delta's end (cx-d7a4d)" + }, + { + "author": "Lawrence Chen", + "title": "optchat-chief: conformance case delta-edit (spec 5a.2), red: an edit of a message the frozen view shows never reaches the next turn (cx-d7a4d)" + }, + { + "author": "Lawrence Chen", + "title": "sidebar-v2 client: rows the document does not place yet keep their personal slot" + }, + { + "author": "Lawrence Chen", + "title": "test(cmux-next): the display-sleep insert tests turn ui.animations.newWorkspace on" + }, + { + "author": "Lawrence Chen", + "title": "sidebar-v2 merge fixes: feat removed transientTopSection, feat's itemOrder names its top band 'shown'" + }, + { + "author": "Lawrence Chen", + "title": "sidebar debug report: build debug.sidebar_rows in CmuxNextSidebar (App size)" + }, + { + "author": "Leo Li", + "title": "test: composer-top-strip-variants declares a 300 s file limit" + }, + { + "author": "Leo Li", + "title": "webviews: drop #21020's gallery reader fix; feat-cmux-next has its own (589f575f5c16)" + }, + { + "author": "Leo Li", + "title": "cmux-next composer: an outside press only closes a menu; Escape returns to the chip" + }, + { + "author": "Leo Li", + "title": "webviews: test how the composer's menus open and close under the mouse (failing)" + }, + { + "author": "Leo Li", + "title": "feat: topStripStyle=tray, a filled tray tucked under the composer card" + }, + { + "author": "Leo Li", + "title": "test: topStripStyle=tray, a tray tucked under the card (red)" + }, + { + "author": "Leo Li", + "title": "fix: plain top strip leaves no side hairline above the card's corners" + }, + { + "author": "Leo Li", + "title": "test: plain top strip draws nothing in the gap above the card (red)" + }, + { + "author": "Leo Li", + "title": "cmux-next composer: chips press like Codex's (arrow cursor, instant press, no stray ring, 28 px folder target)" + }, + { + "author": "Leo Li", + "title": "webviews: test how a press on the composer's chips feels (failing)" + }, + { + "author": "Leo Li", + "title": "webviews: bootstrap reader test without implied eval (from #21020)" + }, + { + "author": "Leo Li", + "title": "webviews: gallery reads a Swift double backslash in bootstrapScript as one" + }, + { + "author": "Leo Li", + "title": "webviews: test that the gallery reads WebTheme.bootstrapScript's Swift backslashes" + }, + { + "author": "Lawrence Chen", + "title": "sidebar-v2: a moved row has new neighbours on both sides; ticks stay patches" + }, + { + "author": "Lawrence Chen", + "title": "sidebar-v2: structural reloads anchor on the first visible row that stayed in place" + }, + { + "author": "Lawrence Chen", + "title": "sidebar-v2 row hold off (hitch17: 175/128 jumps in scenarios 4/5, hitch16 without it: 0)" + }, + { + "author": "Lawrence Chen", + "title": "sidebar-v2: move the lane's logic out of CmuxNextApp (SW14 size cap)" + }, + { + "author": "Lawrence Chen", + "title": "sidebar-v2 row hold review fixes: each listed copy keeps its own row state; a hold that outlives its landing releases" + }, + { + "author": "Lawrence Chen", + "title": "sidebar-v2 drop: row patches wait while a drag, its settle or its card's landing runs (SidebarRowHold)" + }, + { + "author": "Lawrence Chen", + "title": "sidebar-v2 record script: --ticking writes the OSC 7501 loop to every terminal id in `terminal list` (hitch15: the JSON items did not name their workspace, so no terminal matched); prints the list" + }, + { + "author": "Lawrence Chen", + "title": "sidebar-v2 record script: after --stress setup, focus the newest workspace (right under Pinned; the list reveals it), then short wheel gestures with a sign that follows the Pinned block (hitch13: long trackpad gestures over ~17000 pt jumped both ways and never reached the top); wheel and drag only rows at y >= 40-60 (hitch13: a row at y 13.5 was under the titlebar band, its drag never started)" + }, + { + "author": "Lawrence Chen", + "title": "sidebar-v2 record script: --ticking N (at most 60): of the --stress workspaces, N get a terminal whose program reports OSC 7501 working/idle every 250 ms during the drags (agent load as in sidebar-rows-perf-live.py); made last so they sit at the list's top, on screen; the rest stay --empty" + }, + { + "author": "Lawrence Chen", + "title": "sidebar-v2 live link favicon steps: sidebar.get through the app socket names its session as well as its machine (live21: 'required selector is missing' for session, so icon_url read None while the row drew the stored favicon); a sidebar.get error prints once per distinct error" + }, + { + "author": "Lawrence Chen", + "title": "sidebar-v2 undo: each sidebar step is a top-level undo group: by-event grouping is off while the step opens its explicit group (beginUndoGrouping at level 0 first opened the run loop's automatic group and nested the step in it, so two quick section edits whose replies came in one pass were one Edit > Undo, live21); debug.toast reports undo_steps; live step waits for both steps on the stack before Edit > Undo" + }, + { + "author": "Lawrence Chen", + "title": "sidebar-v2 debug.menu_item: undo:/redo: through typed selectors (an @objc protocol + #selector), no NSSelectorFromString (safe-push crash ratchet dynamic_dispatch); other actions are refused with the supported list" + }, + { + "author": "Lawrence Chen", + "title": "sidebar-v2 record script: --stress workspaces are made with --empty (no terminal each: hitch11 started ~790 terminal hosts and used every PTY on cmux-lawrence-2); stops after 20 creates if the PTY count still grows; at the end ends the tag's terminal hosts with stop_tag_daemon.py and prints the PTY count before and after" + }, + { + "author": "Lawrence Chen", + "title": "sidebar-v2 record script: wheel the list to its top with debug.sidebar_wheel trackpad gestures (hitch11: phased debug.mouse scrolls moved it once, 2400 pt, then never again), line wheel after 3 stuck gestures; scenarios 4 and 5 drag only rows on screen (hitch11 started a drag at y -455)" + }, + { + "author": "Lawrence Chen", + "title": "sidebar-v2 record script: after --stress setup, wheel the list to its top until both Pinned tiles have a frame (new workspaces go to the top and Pinned is a block at the list's top: setup1 found Pinned at y -14440 and Alpha at y 1818, never on screen together); scenario 1 drags the first workspace row under Pinned at 1000 workspaces" + }, + { + "author": "Lawrence Chen", + "title": "sidebar-v2 record script: --setup-only (window snapshot + debug.sidebar_rows dump after the setup); the cua-driver session starts after the stress setup (hitch10: the 1000-workspace setup outlived its idle TTL, 'session has ended')" + }, + { + "author": "Lawrence Chen", + "title": "sidebar-v2 drop: a top-level slot in WorkspaceOrdering.rootIndex counts every node as SidebarRow.siblingIndex does (an item or a group with no workspace keeps its slot, only a moved loose workspace leaves its own), and WorkspaceMovePlan.anchor reads a group slot among the group's member rows (SidebarGroup.members)" + }, + { + "author": "Lawrence Chen", + "title": "sidebar-v2 drop: a tab dropped on a group slot by the older resolver (sidebar_drop tab_drop, whose index is the row's member siblingIndex) lands at the slot shown: WorkspaceOrdering.rootIndex and WorkspaceMovePlan.excluding count the group's member rows (SidebarGroup.members: workspaces and link, tab and app items), not its workspaces only" + }, + { + "author": "Lawrence Chen", + "title": "sidebar-v2 record script: after --stress setup, wheel toward Alpha (hitch9: Alpha sat below the window at y 1218 and the upward wheel did not reach it); no CLI focus by row UUID" + }, + { + "author": "Lawrence Chen", + "title": "sidebar-v2 undo: each sidebar step is registered in its own explicit undo group with its action name, so one Edit > Undo undoes exactly one user action (two replies in one run-loop pass no longer share a by-event group); live step: two quick section edits, one Edit > Undo undoes only the second, the next the first" + }, + { + "author": "Lawrence Chen", + "title": "sidebar-v2 undo: revert the key router's Cmd-Z route (Cmd-Z follows the responder chain: Edit > Undo undoes the window's sidebar step when the sidebar or window has focus); debug.menu_item {action, window_number} sends a menu action up a window's responder chain; the live late-undo step uses it for Edit > Undo and Edit > Redo" + }, + { + "author": "Lawrence Chen", + "title": "sidebar-v2 undo: Cmd-Z and Shift-Cmd-Z run the window's sidebar undo stack from the key router when a sidebar step is on top (Edit > Undo has no target in a window that is not key: live18's late Cmd-Z did nothing); the toast's Undo runs its own step again (no stack undo from the toast); the live late-undo step records the key's reply and needs a real undo before it counts the redo" + }, + { + "author": "Lawrence Chen", + "title": "sidebar-v2 record script: after --stress setup, focus Alpha and wheel up in trackpad phases until Alpha and the Pinned tiles are on screen (hitch8: plain wheel events did not move the list); print what it found; scenario 1 is skipped, not a crash, when a tile has no frame" + }, + { + "author": "Lawrence Chen", + "title": "sidebar-v2 record script: Instruments writes its ktrace intermediates to a per-run TMPDIR that is deleted once the .trace is exported (and at exit); unopened instruments*.ktrace files born during this run's trace in the user temp dir are deleted too (they filled cmux-lawrence-2's disk)" + }, + { + "author": "Lawrence Chen", + "title": "sidebar-v2 undo: the window's undo stack calls the step through a selector (the step is held while it is on a stack), not a closure with MainActor.assumeIsolated (crash ratchet)" + }, + { + "author": "Lawrence Chen", + "title": "sidebar-v2 undo: the redo step an undo puts is filled only by its own inverse (the doc store carries the step as the change's origin to onUndoable; a sync inverse fills it while it runs); a refused or no-op inverse removes the empty step" + }, + { + "author": "Lawrence Chen", + "title": "sidebar-v2 undo: an inverse run from the undo stack fills a step put at once on the other side (a daemon reply comes later), so Shift-Cmd-Z redoes; the toast's Undo runs the stack's undo when its step is the top; a document-backed group drop puts no second legacy undo step; the live late-undo step has no redo fallback" + }, + { + "author": "Lawrence Chen", + "title": "sidebar-v2 undo: a pin or sidebar move's undo step also goes on the window's undo stack, so Cmd-Z undoes it after the toast hid (the toast only hides; it keeps Cmd-Z while it shows and its step is the stack's top); live step: Cmd-Z 10 s after the toast hid, then Shift-Cmd-Z" + }, + { + "author": "Lawrence Chen", + "title": "sidebar-v2 live link steps: debug.surfaces reports a browser pane's page url; step 5 needs a new github.com pane, 5b a newly focused one after showing a workspace without it; each drop is undone at once (the 6 s undo toast had ended during the open and favicon waits); sidebar.get through the app socket names its machine (it failed with a missing selector, so icon_url read None)" + }, + { + "author": "Lawrence Chen", + "title": "sidebar-v2 record script: after --stress setup, wheel the list back to its top so Alpha and the Pinned tiles have on-screen frames (hitch7 failed on a None tile frame)" + }, + { + "author": "Lawrence Chen", + "title": "sidebar-v2 drag land: a new drag or a detach ends a flying card first, a released held row shows only if it still draws a shown row, one list reload per drop" + }, + { + "author": "Lawrence Chen", + "title": "sidebar-v2 drag land: a drop's rows and blocks reach the list in one reload, the card retargets to the dropped item while it flies, a group card holds its shape until the model shows it" + }, + { + "author": "Lawrence Chen", + "title": "sidebar-v2 group members: a group's drop index counts its member rows everywhere (drag, keyboard, doc target, edits), a leaving workspace's items keep their place, and a group holding only items is not empty" + }, + { + "author": "Lawrence Chen", + "title": "sidebar-v2 live step 5b: the member-row click must change the github.com surfaces (focus moves to a workspace row first; step 5 already left github.com open)" + }, + { + "author": "Lawrence Chen", + "title": "sidebar-v2 group members: a url, tab or app item inside a group draws as a member row in document order (Pinned, custom and machine sections), clickable, selectable and draggable like a loose item row; live step 5b drops a link onto a Pinned group" + }, + { + "author": "Lawrence Chen", + "title": "sidebar-v2 live script: the link drops above the first ungrouped workspace row of the machine list (live12 dropped it into a Pinned group's members)" + }, + { + "author": "Lawrence Chen", + "title": "sidebar-v2 record script: a fresh cua-driver session label per run, started with start_session (the fixed label had ended, so every call was rejected: hitch5, ptr6, hitch6)" + }, + { + "author": "Lawrence Chen", + "title": "sidebar-v2 live script: the link drops above the list's first row (Alpha is a Pinned tile by step 5; live11 failed on the missing Alpha row, the link itself was added)" + }, + { + "author": "Lawrence Chen", + "title": "sidebar-v2 record script: wait up to 30 s for the tagged app's window to be on screen before grounding cua-driver (hitch5 found none right after launch); fail the run with what cua listed" + }, + { + "author": "Lawrence Chen", + "title": "sidebar-v2 drag land review fixes: the dropped rows under the landing card stay suppressed until it is gone (a reload under the flight does not fade them in or swap an unheld view); a settle that ended inside the drop's reload keeps its target; finishLand restores only views still in the list" + }, + { + "author": "Lawrence Chen", + "title": "sidebar-v2 drag: the card lands on the frame where the row or tile then draws, read from the views the layout just applied (same transaction): land() uses the dragged rows' model frames, landSettled retargets to the dropped rows (workspace, group and members, listed item; a tile dropped into the list lands as its row) else the tiles; displayed geometry lagged the views on the document path (ptr5 settle 2-108 pt)" + }, + { + "author": "Lawrence Chen", + "title": "sidebar-v2 motion checks: a step counts per 120 Hz frame (a late display frame spans several), and hidden views (alpha 0, a dragged group's members) are not judged; settle compares the card with the dropped row's first drawn frame" + }, + { + "author": "Lawrence Chen", + "title": "sidebar-v2 favicons review fixes: one origin -> favicon table per change for every link (no links x tabs scan), skipped when no address moved; debug open_tab_favicons by origin; the live step reads sidebar.get with --json and matches the exact https://github.com origin" + }, + { + "author": "Lawrence Chen", + "title": "sidebar-v2 favicons: link favicon addresses are stored when an open tab's favicon address changes even with the image cached (the store watches each tab's page and favicon address); debug rows show the drawn icon_address and the open tabs' favicons; the live link step checks sidebar.get icon_url == the open tab's favicon and the row draws it (not /favicon.ico)" + }, + { + "author": "Lawrence Chen", + "title": "sidebar-v2: Add to Sidebar (sidebar.item.add, cmux sidebar add-item) takes an http(s) address and adds a link, on the document path too; the live link step adds it with the bundled cmux, opens it, then checks the favicon the open tab teaches; debug.sidebar_apply removed (no step needs it)" + }, + { + "author": "Lawrence Chen", + "title": "sidebar-v2: debug.sidebar_apply sends document ops through the app's store (mirror, daemon, one undo step); the live link step adds its GitHub link with favicon there (the bundled cmux has no raw verb), and the bookmarks steps name Pinned by id (sec_pinned has no title)" + }, + { + "author": "Lawrence Chen", + "title": "sidebar-v2 record script: every cua-driver call uses one session, and a fresh get_window_state grounds each drag (ptr4 1014-101119-0fef0c: the drag replied screenshot_context_missing); a reply with a code counts as failed" + }, + { + "author": "Lawrence Chen", + "title": "sidebar-v2 live script: the link step adds a GitHub link with its favicon through the daemon (sidebar.apply item.add with icon_url), drags it into the list, checks the row draws the favicon, opens it on click and undoes the drop; it no longer skips" + }, + { + "author": "Lawrence Chen", + "title": "sidebar-v2 live script: the Remove from Sidebar and Reset steps use a built-in item (bookmarks) in Pinned; sidebar.item.add takes no links (live7 refused example.com with no such sidebar item)" + }, + { + "author": "Lawrence Chen", + "title": "sidebar-v2 record: wait on debug.sidebar_rows drag_active (a tile drag hides no row, so dragging stayed empty); a drag still active before or 10 s after a gesture stops the run; CHECKS.json records the harness failure; window_record takes up to 12 s and a real-pointer scenario records 10 s" + }, + { + "author": "Lawrence Chen", + "title": "sidebar-v2 record script: a real-pointer run stops with FAIL when the app reports no drag within 5 s of the cua-driver call (a dead harness never records a still sidebar as data)" + }, + { + "author": "Lawrence Chen", + "title": "sidebar-v2 record script: a real-pointer scenario is timed from the drag the app reports (cua-driver's call returned before the gesture ran, so job 1014-082101-bac11c recorded a still sidebar); Escape is timed from that start; the cua reply is printed; frames record 8 s" + }, + { + "author": "Lawrence Chen", + "title": "sidebar-v2 client review fixes: the workspace list shows its machine sections' alignment and spacing; Remove from Sidebar removes a group or unknown item by id (no document ref); the planner notes remove_ref/reset end a batch; live Reset step re-adds the link and checks Pinned's defaults" + }, + { + "author": "Lawrence Chen", + "title": "PKG: pin CCmuxAppFFI to cmux-app-ffi-57941d6f79c7 (sidebar doc slice 4: align, gap, item.remove_ref, reset in the mirror reducer)" + }, + { + "author": "Lawrence Chen", + "title": "sidebar-v2 live script: alignment, spacing, Remove from Sidebar and Reset through the sidebar document, each undone with Cmd-Z; debug.sidebar_rows lists layout_sections (align, gap, item count)" + }, + { + "author": "Lawrence Chen", + "title": "sidebar-v2 client: alignment, spacing, Reset and Remove from Sidebar go to the sidebar document (doc slice 4: section align/gap, section.update {align, gap}, item.remove_ref, reset); the document's align/gap are read into the section arrangement" + }, + { + "author": "Lawrence Chen", + "title": "plans: daemon-capabilities.json lists placement-shift-v1 (DaemonCapabilityExportTests order)" + }, + { + "author": "Lawrence Chen", + "title": "sidebar-v2 client: placement-shift-v1 is listed in DaemonCapabilities.optional (the bundled daemon serves it) and kept out of the plain advertised list: only the document path echoes it" + }, + { + "author": "Lawrence Chen", + "title": "sidebar-v2 client: the placement-shift echo flag is a locked static (no nonisolated(unsafe): the crash ratchet refused it)" + }, + { + "author": "Lawrence Chen", + "title": "tests: SpareNewTabChatOpensTabsTests builds AgentTabStore(build:) (feat-cmux-next 1746e00607ea landed it with the old tag: label after 677f1e1a0248 renamed it; the tip does not compile its tests)" + }, + { + "author": "Lawrence Chen", + "title": "sidebar-v2 record script: find the tagged app's pid by its debug socket (lsof), then by the bundle's real or given path; the real-pointer baseline job failed because pgrep found no process" + }, + { + "author": "Lawrence Chen", + "title": "sidebar-v2 client review fixes: a section added with its items adds them too (Add to Top or Pin into an empty band; an existing Pinned takes only the items); a band edit refused at once throws to the caller (CLI/MCP get the error); the workspace list takes only look/arrangement/columns/max rows; Remove everywhere removes every non-workspace copy at any depth; every user's band edit is one undo step with the document; a section placed at the workspace list anchors before the first machine section; the older owner's capability no longer gates band edits while the document is active" + }, + { + "author": "Lawrence Chen", + "title": "sidebar-v2 client: SidebarSectionStrings imports CmuxNextSidebar (LayoutOpGap)" + }, + { + "author": "Lawrence Chen", + "title": "PKG: app FFI pin cmux-app-ffi-5e212ffa (doc slice 2) and CMUX_SIDEBAR_MIRROR_FFI on CmuxNextSidebar (the define came in d917da33f7ed; feat already pins 579db042 without it)" + }, + { + "author": "Lawrence Chen", + "title": "sidebar-v2 client: region cards and section lines are kept by section id (not by index), so an added or removed section never moves a neighbour's card or line on the drag spring" + }, + { + "author": "Lawrence Chen", + "title": "sidebar-v2 client: with sidebar-doc-v1 active every band edit goes to the document (one sidebar.apply, one undo step), not to the older sidebar_layout owner: section add/rename/look/arrangement/columns/max rows/title/space scope/move/remove, item add/remove/remove everywhere/label toggle, Add to Top, drop-to-pin and Add Group to Section; a workspace added to a band moves (or is adopted) there and leaves a band by unpin; alignment, spacing and reset are unavailable (the document has no field for them)" + }, + { + "author": "Lawrence Chen", + "title": "sidebar-v2 client: an empty custom section stays reachable: outside a drag it draws its title in every look (no title: no space); during a drag it opens a one-row drop zone under its title that takes the drop" + }, + { + "author": "Lawrence Chen", + "title": "sidebar-v2 debug: debug.sidebar_rows lists section headers (id, title, window frame) of the band and the list blocks, so a proof can aim a drop at an empty custom section" + }, + { + "author": "Lawrence Chen", + "title": "sidebar-v2 live script: the 4 FAILs were script assumptions, not app bugs: the collapse step selects a loose row (the undo toast redoes, so Alpha stays a tile); Grp2 is found by group id (group rows carry no title); the tile drop and the filtered reorder read the row order off the screen (new workspaces list newest first) and the undo check restores that order" + }, + { + "author": "Lawrence Chen", + "title": "sidebar-v2 client review fixes: a drop that sends nothing ends its settle; the dropped item stays invisible under the landing card and shows in the card's last transaction; a screenless window lands at once; the tile gap underlay opens with the rows; non-animated reloads under a drag or settle adopt too; a recycled block takes its content at once; fading rows stay in the probe; the shadow model always holds the current shape; record script stops the app on every failure and ends scenario 4 in the autoscroll band" + }, + { + "author": "Lawrence Chen", + "title": "sidebar-v2 client: the drag never reloads; rows, blocks, tiles, cards and lines move on one additive .move spring (SidebarDragSpring); drops, refusals and settle ends adopt the drag's look with no jump; the card lands on the same spring with its shadow shape and holds its slot until the model shows the drop; probe records opacity, revision, settling; record script drives the real pointer with cua-driver, adds a refusal scenario, 8 pt / 1 pt / echo checks and an Animation Hitches trace" + }, + { + "author": "Lawrence Chen", + "title": "sidebar-v2 client review fixes: batches during the first load apply after it; a held drag rebuilds its hit geometry when the rows change; hit y from the rest shape (no morph oscillation); refused dim when nowhere; a tile drag lands on its tile; rest frame without the group gutter; numeric revisions; the record script fails an empty or unfollowed recording" + }, + { + "author": "Lawrence Chen", + "title": "sidebar-v2 client: the card lifts in place (1.03 scale about its centre, back to 1 on the settle); record script names its real-pointer prerequisite" + }, + { + "author": "Lawrence Chen", + "title": "sidebar-v2 client: the motion probe holds the list weakly (crash ratchet)" + }, + { + "author": "Lawrence Chen", + "title": "sidebar-v2 client: the lifted card morphs to the drop's shape (additive springs, origin-only follow), settles into the slot's final frame; per-frame motion probe (debug.sidebar_rows motion) and sidebar-v2-drag-record.py frame checks" + }, + { + "author": "Lawrence Chen", + "title": "sidebar-v2 client: drops settle in place, refusals spring back, empty sections take drops, band spacing" + }, + { + "author": "Lawrence Chen", + "title": "PKG: app FFI pin cmux-app-ffi-579db042 (sidebar document mirror) and CMUX_SIDEBAR_MIRROR_FFI on CmuxNextSidebar" + }, + { + "author": "Lawrence Chen", + "title": "sidebar-v2 client: the mirror's handle frees from a nonisolated deinit (compiles with CMUX_SIDEBAR_MIRROR_FFI)" + }, + { + "author": "Lawrence Chen", + "title": "sidebar-v2 client: close for a remote machine's closed workspace; icon_url from the item's extra too (doc lane a1fbb874)" + }, + { + "author": "Lawrence Chen", + "title": "sidebar-v2 drag proof: every drop look is a gap or a group fill" + }, + { + "author": "Lawrence Chen", + "title": "sidebar-v2 client: one section renderer, tile gaps, item rows, link favicons" + }, + { + "author": "Lawrence Chen", + "title": "sidebar-v2 client: mirror FFI per the contract amendments (view and drag_begin reply bare, apply_intent's stamped ops sent)" + }, + { + "author": "Lawrence Chen", + "title": "sidebar-v2 drag proof: group in Pinned lists and collapses, link row opens, drop indicator per drag" + }, + { + "author": "Lawrence Chen", + "title": "sidebar-v2 client: one list for every section, link rows, one drop look" + }, + { + "author": "Lawrence Chen", + "title": "sidebar-v2 drag proof: reorder while filtering through debug.sidebar_filter" + }, + { + "author": "Lawrence Chen", + "title": "sidebar-v2 client: debug.sidebar_filter uses the control JSONValue" + }, + { + "author": "Lawrence Chen", + "title": "sidebar-v2 client: debug.sidebar_filter imports JSONValue" + }, + { + "author": "Lawrence Chen", + "title": "sidebar-v2 client: group edits as sidebar.group.* (collapse in the doc), adopt+move in one sidebar.apply, adopt retry, keyboard reorder by the visible order while filtering, band reorder as one sidebar.move, debug.sidebar_filter" + }, + { + "author": "Lawrence Chen", + "title": "sidebar-v2 client: review fixes (document revision from the marker, no-op intents dropped, pinned group members placed once, sectionless machines adopt, only workspaces and groups drop on the list, header drops accepted, queued refetch)" + }, + { + "author": "Lawrence Chen", + "title": "sidebar-v2 client: main-actor store callbacks" + }, + { + "author": "Lawrence Chen", + "title": "sidebar-v2 client: a move of an unplaced item sends nothing" + }, + { + "author": "Lawrence Chen", + "title": "sidebar-v2 client: public Foundation imports; live drag proof script" + }, + { + "author": "Lawrence Chen", + "title": "sidebar-v2 client: FFI call counts by entry; drop duplicate JSONValue.arrayValue" + }, + { + "author": "Lawrence Chen", + "title": "sidebar-v2 client: match the doc lane's mirror ABI (string replies, {idempotency_key, ops}, rejected batches, view/table shapes, arrangement names)" + }, + { + "author": "Lawrence Chen", + "title": "sidebar-v2 client: non-trapping revision parses (crash ratchet)" + }, + { + "author": "Lawrence Chen", + "title": "CmuxNext sidebar-v2 client: sidebar document client, mirror wrapper, read path, move intents, drag geometry (behind sidebar-doc-v1)" + } + ], + "shortVersion": "1.0.0-nightly.3889441310601", + "summary": [ + { + "group": "fixed", + "title": "Plain top strip leaves no side hairline above the card's corners" + }, + { + "group": "changed", + "title": "Cloud Chief prompt: the three note forms and that a note's target is a message id (hq-6d…" + }, + { + "group": "changed", + "title": "Chief hands, Mac classifier: re-review fixes (3 P1)" + }, + { + "group": "changed", + "title": "Chief hands, Mac classifier: review fixes (2 P0, 4 P1, P2s)" + }, + { + "group": "changed", + "title": "Chief hands: the Mac auto-mode classifier (off until tested), hand hard denies, the…" + }, + { + "group": "changed", + "title": "Sidebar mirror: nonisolated deinit" + }, + { + "group": "changed", + "title": "An outside press only closes a menu; Escape returns to the chip" + }, + { + "group": "changed", + "title": "Chips press like Codex's (arrow cursor, instant press, no stray ring, 28 px folder target)" + } + ], + "version": 1 + }, + { + "build": "3886569630501", + "changes": [], + "date": "2026-10-16", + "head": "50af7da55dbb696e5ed84278b73120ef084dd9b6", + "highlights": [ + { + "body": "`cmux acp daemon shutdown` now stops only the agent daemon: agents keep running and the next daemon picks them up, the same as a restart or an update. Add `--end-agents` to end every agent too. Before, a plain shutdown ended every agent on the machine, including agents that other windows or other people were using.", + "id": "acp-shutdown-keeps-agents", + "media": [], + "title": "Stopping the agent daemon keeps your agents running" + }, + { + "action": { + "id": "browserDevice", + "title": "Emulate device" + }, + "body": "Emulate Device… in the browser's Tools menu (or the palette) shows every device of Chrome's device toolbar, grouped as Chrome groups them, and newer devices that Chrome does not list yet. In a Chromium tab the page gets the device's viewport, pixel ratio, user agent, client hints, touch and mobile layout, as in Chrome's device mode. A WebKit tab gets the viewport, pixel ratio and user agent. Choose an orientation or the unfolded screen of a foldable from the same menu.\n\nAgents and scripts use the same list: `cmux browser devices list`, `cmux tab emulate --device \"iPhone 16 Pro\"`, and `cmux browser devices add` for your own devices in Chrome's device format.", + "id": "browser-device-emulation", + "media": [], + "title": "Emulate phones, tablets and foldables in the browser" + }, + { + "action": { + "id": "browserProfile.moveTab", + "title": "Try it" + }, + "body": "Move Tab to Browser Profile now keeps the tab: same place, same tab, and the page reloads at the same address in the new profile, with that profile's cookies, site data and permissions. Back and forward history starts over in the new profile, and unsaved form input on the page is lost. Agents can create browser profiles, open a tab in one and move a tab to another from the command line: `cmux browser profile create --name Work`, `cmux browser profile open --engine webkit --profile Work` and `cmux browser tab set-profile --profile Work` (also an MCP tool). Agents cannot delete a profile.", + "category": "new", + "id": "browser-profile-move-tab-in-place", + "media": [], + "title": "Move a tab to another browser profile without losing its place" + }, + { + "body": "When a chat on an SSH machine asks to run a command, Allow now runs it there. Before, the first Allow on that machine did nothing, because its agent service did not hold this Mac's approval key. cmux now gives the key before the chat starts when nothing else runs on that machine's agent service. When other agents run there, cmux asks first: the chat shows a Restart button, and the running agents keep working through the restart.", + "id": "ssh-chat-allow", + "media": [], + "title": "Allow works for chats on SSH machines" + }, + { + "body": "A new chat in an SSH workspace now asks whether you trust its folder on that machine, the same question a chat on this Mac asks. Choose Trust and the chat starts there. Before, the send failed with \"not a trusted folder\" and the app had no way to answer. New Agent Chat from an SSH workspace also starts in a folder of that workspace on the machine, not with \"Open a terminal in a folder first\".", + "id": "ssh-chat-folder-trust", + "media": [], + "title": "Chats on SSH machines ask to trust their folder" + } + ], + "items": [ + { + "author": "Leo", + "pr": 20455, + "title": "ci(cx-g34i): resume deferred DEV builds after branch moves" + }, + { + "author": "Lawrence Chen", + "title": "Chief hands: staging sandbox image cmuxnp-stg-hand-v2 (no stale nvm claude ahead on PATH)" + }, + { + "author": "Lawrence Chen", + "title": "ci: the real import test carries the Developer ID G2 intermediate in its .p12" + }, + { + "author": "github-actions[bot]", + "title": "chore(next): base autofix at 8dd733c2d190" + }, + { + "author": "Lawrence Chen", + "pr": 21143, + "title": "ci: accept a Developer ID intermediate that the signing .p12 already added" + }, + { + "author": "Leo", + "pr": 21076, + "title": "feat(agent-chat): stream ACP tool progress" + }, + { + "author": "Lawrence Chen", + "title": "OptChat 5a review fixes: frozen view keeps its unbuilt lines as placeholders (bytes never change), unbuilt imported tail stays out of the delta, a turn's new messages always start a block, re-render rule (a) needs a built fold above level 0 over the front, stale frozen views ignored, a failed turnInput re-folds the core after rollback, skipped view mark logged" + }, + { + "author": "Lawrence Chen", + "title": "live test: the posted reply is the streamed text trimmed" + }, + { + "author": "Lawrence Chen", + "title": "OptChat 5a: a re-render never shows the turn's new messages (spec 7 anchoring)" + }, + { + "author": "Lawrence Chen", + "title": "OptChat 5a cache-stable turn input: optchat-core turn_input (frozen view + append-only delta, re-render at DELTA_MAX with a fold past the front or at DELTA_HARD), wasm turnInput, Cloud brain logs then builds the input, view-end 1 h mark, system prompt rule for delta lines" + }, + { + "author": "Lawrence Chen", + "title": "fix(cmux NEXT): workspace hint chips show the digit Cmd-digit selects" + }, + { + "author": "Lawrence Chen", + "title": "test(cmux NEXT): shortcut hint digit chips select their own row (red)" + }, + { + "author": "Lawrence Chen", + "title": "cmux-next tabs: TabOverflowSetting is a struct with an init, as ChromeStyleSetting, for the package namespace lint (cx-kp9b4)" + }, + { + "author": "Lawrence Chen", + "title": "Model gateway: Claude Code's dated and small/fast model names map to their 5.5 family, or to a model the route serves" + }, + { + "author": "Lawrence Chen", + "title": "Chief hands on staging: the published hand with agent.stop (tree 8d1005fe, source c5b2d249a655)" + }, + { + "author": "Lawrence Chen", + "title": "ci: real import test runs only in CI or by opt-in; pinned Xcode; trunk-only push" + }, + { + "author": "Lawrence Chen", + "title": "cmux-next tabs: the overflow hint's Use Scrolling Tabs hook lives on DesignSettings, set by TabOverflowSetting.bindActions, so CmuxNextApp stays at its size cap (cx-kp9b4)" + }, + { + "author": "Lawrence Chen", + "title": "chief-first-turn-cost: say that real=1 sends turns to count_url, does not check correctness and exits 1 on a route failure (review, cx-d7a4d)" + }, + { + "author": "Lawrence Chen", + "title": "Model gateway (HTTP, Claude Code): map anthropic-beta into Bedrock's anthropic_beta (known betas), drop and log fields Bedrock does not take, log the route's refusal and pass its reason to the caller" + }, + { + "author": "Lawrence Chen", + "title": "Chief hands: sandbox review fixes, the lane's own sandbox image, gateway P2s" + }, + { + "author": "lawrencecchen", + "title": "acpmux no_keychain: the remote chain test never runs the real security program (KEYCHAIN_FAKE_SECURITY: the interposer logs a security start and fails it with ENOENT), so no keychain dialog shows on a shared fleet Mac; the setting-on case requires the attempted start" + }, + { + "author": "Lawrence Chen", + "title": "chief-first-turn-cost: turns=N and real=1 (the real model through the subrouter) print the cache hit of each turn; min_hit fails a warm turn under it (cx-d7a4d)" + }, + { + "author": "Lawrence Chen", + "title": "fix(cmux-next): the fit bar's buttons use TypeScale.emphasis (was .medium) (chief 2026-10-16)" + }, + { + "author": "lawrencecchen", + "title": "cmux-coderouter: drop the unused security-framework dependency (no code uses it after cx-hh0vu and the remote chain keychain gate; other crates keep it in Cargo.lock)" + }, + { + "author": "lawrencecchen", + "title": "acpmux: a remote chain reads this Mac's Claude login from the keychain only while the cmux setting agents.remoteChains.claudeKeychainLogin is true (default off; chief decision after cx-hh0vu)" + }, + { + "author": "lawrencecchen", + "title": "acpmux remote chain keychain read (red): a remote chain reads the Claude login from the keychain only with agents.remoteChains.claudeKeychainLogin on" + }, + { + "author": "Lawrence Chen", + "title": "fix(cmux NEXT): CmuxNextAgentActivity keeps the MainActorLineDrain name (no CmuxNextApp growth)" + }, + { + "author": "Lawrence Chen", + "title": "OptChat 5a: delta entries that edit, retract or delete a view line name it; system prompt rule; conformance case delta-edit" + }, + { + "author": "Lawrence Chen", + "title": "optchat-chief: restore the compactor doc comment a scripted edit broke (cx-oqnw3)" + }, + { + "author": "Lawrence Chen", + "title": "fix(cmux-next): type-scale tokens for the omnibar text and the fit bar sizes; a 14 pt field step (no pixel change)" + }, + { + "author": "Lawrence Chen", + "title": "Chief hands: agent sessions end their model access; sandboxes use a hands-only Freestyle key" + }, + { + "author": "Lawrence Chen", + "title": "OptChat: cache-stable turn input rule (frozen view, append-only delta, re-render bounds) for both brains" + }, + { + "author": "Lawrence Chen", + "title": "chore(cmux NEXT): main-actor work baseline follows SSHService+PersonKey's lower counts" + }, + { + "author": "Lawrence Chen", + "pr": 21139, + "title": "release, nightly: publish the staged release by id, refuse duplicate drafts, resume a complete staged release" + }, + { + "author": "Lawrence Chen", + "title": "fix(cmux NEXT): the line-batch helper's public signature needs a public Foundation import" + }, + { + "author": "Lawrence Chen", + "title": "Runs record the Bedrock region that answered each model call (route header x-bedrock-region, chatmux2 PR 767)" + }, + { + "author": "Lawrence Chen", + "title": "cmux-next: the 57 machine translations of remote.update.title, remote.update.body and remote.button.update use needs_review, like the rest of Remote.xcstrings (cx-3r9mt)" + }, + { + "author": "Lawrence Chen", + "title": "acpmux file: secrets: Windows refuses them (no owner-only check there); Unix-only test; protocol IR + web types current" + }, + { + "author": "Lawrence Chen", + "title": "ci: import the signing certificate as a named .p12; real macOS import test" + }, + { + "author": "Lawrence Chen", + "title": "cmux-next tabs: regenerated settings schema, MDM docs, action surfaces, defaults snapshot and settings page strings (cx-kp9b4)" + }, + { + "author": "Lawrence Chen", + "title": "cmux-next: translate the SSH remote-update prompt (remote.update.title, remote.update.body, remote.button.update) into the 19 missing languages (cx-3r9mt)" + }, + { + "author": "Lawrence Chen", + "title": "Agent tokens live with the agent session (Lawrence 2026-10-15): claim knd agent, open at mint, bound at agent.start, revoked by agent cancel or the hand's session-end hook (revokeAgentSession), same per-token cap; G7 guards CHIEF_BRAIN_*, CHIEF_CREDITS_* and CHIEF_RUN_TOKEN_CAP_USD" + }, + { + "author": "Lawrence Chen", + "title": "fix(cmux NEXT): AcpmuxPersonLine decodes off the main actor and batches its lines" + }, + { + "author": "Lawrence Chen", + "title": "cmux-next tabs: plans record the new minimums and Tab Overflow (cx-kp9b4)" + }, + { + "author": "Lawrence Chen", + "title": "fix(cmux NEXT): BuiltInAdBlockerSetting and PageSelectionMenu are instantiable (package conventions lint)" + }, + { + "author": "Lawrence Chen", + "title": "cmux-next tabs: an opening or closing tab hides its content below Chrome's icon-only width, not the new crowding minimum (cx-kp9b4)" + }, + { + "author": "Lawrence Chen", + "title": "cmux-next tabs: one-time hint at a crowded strip's end: Use Scrolling Tabs? (cx-kp9b4)" + }, + { + "author": "Lawrence Chen", + "pr": 21141, + "title": "pin-cmux-tui: on_origin_branch never looks up origin heads by id (lazy fetch per head in a partial clone)" + }, + { + "author": "Lawrence Chen", + "title": "cmux-next tabs: Tabs: Use Scrolling Tabs and Tabs: Use Shrinking Tabs palette actions (cx-kp9b4)" + }, + { + "author": "Lawrence Chen", + "title": "cmux-next tabs: shrunk tabs keep a readable title (min 76 inactive, 96 selected); Scroll keeps them 140 wide (cx-kp9b4)" + }, + { + "author": "Lawrence Chen", + "title": "cmux-next tabs: tabs.overflow setting, Shrink (default) or Scroll, in the Tabs group (cx-kp9b4)" + }, + { + "author": "Lawrence Chen", + "title": "Production Cloud Chief config (not deployed): brains on, Opus via service-key route, three Claude models, owners by personal team id, Haiku fallback + compactor (charged); HTTP gateway refuses chief tokens (run tokens only), retries a throttled/overloaded route once, settles in waitUntil, deployment cap applies to issued tokens; opencode container route goes through the gateway (credits, allow-list)" + }, + { + "author": "Lawrence Chen", + "title": "Sidebar: keep setWindowVisible at its old size (godfile budget)" + }, + { + "author": "Lawrence Chen", + "title": "fix(cmux NEXT): acpmux prompt text helpers are nonisolated" + }, + { + "author": "lawrencecchen", + "title": "ci: pull request trees carry acpmux in completion.json too (hq-1f, chief decision)" + }, + { + "author": "Lawrence Chen", + "title": "Chief hands on staging: the published hand (tree 4578591f) and the sandbox image" + }, + { + "author": "Lawrence Chen", + "title": "cmux-tui tests: wait on real signals in slow tests (cx-ngrtv)" + }, + { + "author": "Lawrence Chen", + "title": "Sidebar: a covered window's resume reaches row badge spinners (cx-m8buz)" + }, + { + "author": "Lawrence Chen", + "title": "Chief: review fixes (cx-oqnw3, cx-mbbee)" + }, + { + "author": "Lawrence Chen", + "title": "hands: a run token names the brain run and its conversation (revoked when the run ends)" + }, + { + "author": "Lawrence Chen", + "title": "Gateway run tokens: revoked when the run ends or is cancelled, spend cap per token (claim cap, ledger in the run's brain object); outbox: projection explicitly before other targets after MuxDO" + }, + { + "author": "Lawrence Chen", + "title": "outbox: only a Chief's wake queue (MuxDO) goes before the projection; other channels keep their order" + }, + { + "author": "Lawrence Chen", + "title": "outbox: deliver to target objects before the database projection (Chief wakes no longer wait behind the mirror write)" + }, + { + "author": "lawrencecchen", + "title": "ci: publish acpmux for Linux musl and macOS in the cmux-tui tree, listed in completion.json (hq-1f)" + }, + { + "author": "Lawrence Chen", + "title": "Chief hands gateway route: security review fixes" + }, + { + "author": "Lawrence Chen", + "title": "Chief hands: per-run model gateway route (acpmux file: secret refs, a chat's route at creation)" + }, + { + "author": "Lawrence Chen", + "title": "Chief: probe sessions get their own name; a compactor fault is a system notice; cmux chief engine/stop --chief (cx-oqnw3, cx-mbbee)" + }, + { + "author": "Lawrence Chen", + "title": "base-red: cx-2ueez closed_delete restart test is red on Linux too (rbx, alone)" + }, + { + "author": "Lawrence Chen", + "title": "Chief: red behavior tests for cx-oqnw3 (restarted brain's compactor probe, no compactor Chief message) and cx-mbbee (cmux chief engine/stop --chief)" + }, + { + "author": "Lawrence Chen", + "title": "cmux-tui-rust-check: CMUX_RUST_TEST_SHARD=i/n runs nextest partition count:i/n; fmt, clippy and doc tests only in shard 1" + }, + { + "author": "Lawrence Chen", + "title": "Cloud Chief wake path: marks (wake, admitted, settled) on Run.timing, chief record reused 10 s across wake and turn; staging allow-list adds the two test owners that hold staging credits" + }, + { + "author": "Lawrence Chen", + "title": "staging: the Cloud Chief brain O (OpencodeBrainDO, tag v17, its container, CHIEF_OPENCODE_* vars)" + }, + { + "author": "Lawrence Chen", + "title": "Home live: order a run's talk segments by the owner's Step.seq from the rows, never by parsing the step id (cx-5ylym)" + }, + { + "author": "Lawrence Chen", + "title": "Home live: red behavior test, Cloud-shaped step ids (talk:) in home-streaming-live.py --live-frames (cx-5ylym)" + }, + { + "author": "Lawrence Chen", + "title": "live test: final delta, run end, reply in that order" + }, + { + "author": "Lawrence Chen", + "title": "Remove main files added under directories feat-cmux-next deleted (main sync 2026-10-15 second run, cx-q1lnl)" + }, + { + "author": "Lawrence Chen", + "title": "cmux-next settings: regenerate settings schema, MDM and page strings for the tab width settings on feat-cmux-next 3ddff0d5 (fleet export step 882298fd) (hq-1d, no bead)" + }, + { + "author": "Lawrence Chen", + "title": "Cloud Chief: paid-model refusal reason on the run (note step / run error), final delta and run end before the reply" + }, + { + "author": "Lawrence Chen", + "title": "test(cmux-next): the omnibar card's corners are no longer the popup corner (cx-d0d.102)" + }, + { + "author": "Lawrence Chen", + "title": "cmux-next: CmuxNextApp cap +70 for the app-side SSH update prompt (chief go 2026-10-15, cx-3r9mt)" + }, + { + "author": "Lawrence Chen", + "title": "cmux-next: shorter doc comments on the update path, so the app side of cx-3r9mt stays within its +70 (cx-3r9mt)" + }, + { + "author": "Lawrence Chen", + "title": "cmux-next tabs: a new tab opens at the previous tab's right edge as it is on screen and slides with it (Chrome reads the previous tab's current bounds); a slot-based start sat under the still-shrinking previous tab (proof overlap, cx-4t1tc hit test) (hq-1d, no bead)" + }, + { + "author": "Lawrence Chen", + "title": "cmux-next motion: SpringValue.solve is bounded: at rest past min(10 s, 20 x response) or for a non-finite time, move's tuning for a non-finite or non-positive one (at most 100 FFI pieces; hq-4e blocker) (hq-1d, no bead)" + }, + { + "author": "Lawrence Chen", + "title": "cmux-next motion: SpringValue.solve stays, on cmux-motion's closed form through the FFI in 0.1 s pieces (ColorTransition, landed meanwhile, reads it) (hq-1d, no bead)" + }, + { + "author": "Lawrence Chen", + "title": "cmux-next tabs: the closing-mode tracking area lives on the window's content view (AppKit clips it to the strip's bounds otherwise, so the pad never tracked) and its exit reads the pointer (hq-4e check, hq-1d, no bead)" + }, + { + "author": "Lawrence Chen", + "title": "cmux-next tabs: hq-4e review fixes: a closing tab pins to its left neighbour by order, a new first tab opens from width 0, the drag threshold uses the tab actually passed, closing mode ends when the strip leaves its window and on leaving the extended rect (hq-1d, no bead)" + }, + { + "author": "Lawrence Chen", + "title": "cmux-next: the moved remote helpers are instance surfaces (SSHHost.personHolds, SSHHost.updateCheck, RemoteProbe.updateNeed), as the package namespace lint asks (cx-3r9mt)" + }, + { + "author": "Lawrence Chen", + "title": "opencode brain: model routes moved to model-gateway/routes.ts" + }, + { + "author": "Lawrence Chen", + "title": "cmux-next: the agent daemon status, person_holds, the update check and its retry ledger move to CmuxNextRemote (RemoteAgentDaemon.swift), so CmuxNextApp grows less (SW14 size cap) (cx-3r9mt)" + }, + { + "author": "Lawrence Chen", + "title": "cmux-next settings: exports for the tab width settings (settings schema, MDM, defaults snapshot, page strings) and motion.md (hq-1d, no bead)" + }, + { + "author": "Lawrence Chen", + "title": "cmux-tui docs: the build_time known limit for dev builds (cx-3r9mt)" + }, + { + "author": "Lawrence Chen", + "title": "cmux-next tabs: tab width settings (appearance.metrics.tabMaxWidth, tabMinActiveWidth, tabMinInactiveWidth, tabPinnedWidth; Chrome's minimums from the shared tokens, user value wins, min <= max) (hq-1d, Lawrence 2026-10-15, no bead)" + }, + { + "author": "Lawrence Chen", + "title": "cmux-next: an older remote cmux-tui updates by itself only on an idle machine (no live agent, no peer session, no other client's key); else Update available, and the person's Update starts it; build_time is the first build of the cmux-tui source tree (cx-3r9mt)" + }, + { + "author": "Lawrence Chen", + "title": "cmux-next tabs: TabStripMetrics imports CmuxNextDesign publicly (its public chrome field is a MotionTabStrip) (hq-1d, no bead)" + }, + { + "author": "Lawrence Chen", + "title": "cmux-next tabs: review fixes: closing mode exit sees moves outside the app, first tab opens at once, closing first tab keeps its x, active minimum covers icon + close (hq-1d, no bead)" + }, + { + "author": "Lawrence Chen", + "title": "cmux-tui: the plain remote-probe stays under the 4096 bytes every SSH bootstrap reads; the capability list comes only with --build-facts, which the app asks for its update check (cx-3r9mt proof)" + }, + { + "author": "Lawrence Chen", + "title": "cmux-next tabs: hq-4e notes: open/close at width 0 from prev.right (no overlap), comfortable max 240, reorder threshold by the passed tab, retarget only on a pixel change (hq-1d, no bead)" + }, + { + "author": "Lawrence Chen", + "title": "cmux-next tabs: Chrome tab strip motion on cmux-motion tweens; springs step through cmux_motion_step (hq-1d, no bead)" + }, + { + "author": "Lawrence Chen", + "title": "cmux-tui-core: build_capabilities names the browser runtime only where it exists (Windows check) (cx-3r9mt)" + }, + { + "author": "Lawrence Chen", + "title": "brain-stream: syntax" + }, + { + "author": "Lawrence Chen", + "title": "ci: base-red cx-2fi09 (noun-first path, live_reply) and cx-2ueez (split close restore, macOS) until 2026-10-18" + }, + { + "author": "Lawrence Chen", + "title": "runs: timing marks (first model request, first token) for the wake-path measurement" + }, + { + "author": "Lawrence Chen", + "title": "cmux-next: a failed automatic update is tried again after two minutes (a build still being published, a busy machine) (cx-3r9mt)" + }, + { + "author": "Lawrence Chen", + "title": "gateway review fixes: a key per call and the terminal event after the charge, route headers only to the Claude route, meter outage waits instead of skipping, test env restored" + }, + { + "author": "Lawrence Chen", + "title": "gateway http: the charge ends the stream" + }, + { + "author": "Lawrence Chen", + "title": "Model gateway over HTTP: POST /v1/model-gateway/v1/messages with per-run tokens or chief tokens, credits held and charged from the stream's usage" + }, + { + "author": "Lawrence Chen", + "title": "cmux-next: review fixes: an automatic update skips a plan that installs the build the machine runs, refuses when the machine's binary changed meanwhile, never marks a working link as failed; the install lock is refreshed and taken over atomically; no agent-daemon handoff while peer sessions run; update-need lint fixes (cx-3r9mt)" + }, + { + "author": "Lawrence Chen", + "title": "gateway test: paid fallback served by the route (red before the gate)" + }, + { + "author": "Lawrence Chen", + "title": "Model gateway in process: service-key route auth, credits around every upstream attempt, compactor charged, run usage, paid fallback through the same gate, credits admit + one notice, hands tools, CP initialize/chiefs/manage/cursor" + }, + { + "author": "Lawrence Chen", + "title": "cmux-remote: rustfmt (cx-3r9mt)" + }, + { + "author": "Lawrence Chen", + "title": "cmux-tui: rustfmt (cx-3r9mt)" + }, + { + "author": "Lawrence Chen", + "title": "cmux-next: on connect an SSH machine whose cmux-tui is older (remote update-need) gets the app's build, with its session and agent daemons handed over; one install per machine at a time, from any Mac (cx-3r9mt)" + }, + { + "author": "Lawrence Chen", + "title": "feat(cmux-next): omnibar at 28 pt / 14 pt at every density, its own card color and 12 pt card corners (cx-d0d.102)" + }, + { + "author": "Lawrence Chen", + "title": "cmux-tui: remote update-need orders two builds (capabilities first, then the build time); remote-probe names build_time and daemon_capabilities (cx-3r9mt)" + }, + { + "author": "Lawrence Chen", + "title": "cmux-next: the keyed restart asks person_holds once more when the ssh call drops, so a new acpmux run never holds a key the app did not bind (cx-hd3rw)" + }, + { + "author": "Lawrence Chen", + "title": "cmux-next: after a remote install the machine's acpmux is handed over to the new binary, its hosted agents kept (keyed restart, only when it keeps agent hosts) (cx-brq9m)" + }, + { + "author": "Austin Wang", + "pr": 20828, + "title": "Custom sidebar: expose workspace emoji in data context" + }, + { + "author": "Austin Wang", + "pr": 20804, + "title": "Fix Claude Teams tmux shim with custom Claude path" + }, + { + "author": "Lawrence Chen", + "title": "measure: chief_driver falls back to plain `daemon shutdown` when an acpmux from before --end-agents (cx-qryd0) refuses the flag; its plain shutdown already ends agents" + }, + { + "author": "Austin Wang", + "pr": 17616, + "title": "fix(sidebar): refresh workspace names after rename" + }, + { + "author": "Austin Wang", + "pr": 20352, + "title": "fix: keep Antigravity sessions attached after relaunch" + }, + { + "author": "Lawrence Chen", + "title": "Chief Home: move the send-ask rule and the named-Chief lookup into CmuxNextHomeEngine (app size cap; cx-4io0o, cx-327wl)" + }, + { + "author": "Lawrence Chen", + "title": "Chief Home: review fixes (cx-4io0o, cx-327wl, cx-di8pd)" + }, + { + "author": "Lawrence Chen", + "title": "Chief Home: a send is an ask; named Chief controls name their Chief; a rename retitles (cx-4io0o, cx-327wl, cx-di8pd)" + }, + { + "author": "Lawrence Chen", + "title": "Chief Home: red behavior tests for cx-4io0o, cx-327wl, cx-di8pd" + }, + { + "author": "Leo", + "pr": 21108, + "title": "cmux-next control: name homeChannelsEnabled in the bridge context table (completes ea28ba31082e, base red)" + }, + { + "author": "Leo", + "pr": 21040, + "title": "Channels: a real menu on selected message text, and Quote in Reply" + }, + { + "author": "Leo", + "pr": 20901, + "title": "cmux-next: session side rail behind Debug Settings (cx-ncc.101)" + }, + { + "author": "Leo", + "pr": 21102, + "title": "cmux-tui: a reattached terminal keeps its prompt and activity (cx-6so.59)" + }, + { + "author": "Leo", + "pr": 21104, + "title": "acpmux: take the workspace from CMUX_WORKSPACE_ID and refuse a mismatch" + }, + { + "author": "Lawrence Chen", + "title": "free tier test: drop the replaced provider stream, no shutdown (ENOTCONN on macOS)" + }, + { + "author": "Leo", + "pr": 21057, + "title": "fix: the Channels live typing row has no tooltip over its own text" + }, + { + "author": "lawrencecchen", + "title": "cmux-tui: install the terminal-host executable when the daemon starts serving, not on its first terminal (cx-b4sjc)" + }, + { + "author": "lawrencecchen", + "title": "cmux-tui: debug timing marks on the whole resource create path (cx-b4sjc)" + }, + { + "author": "Leo", + "pr": 21008, + "title": "Notifications: a finished turn's banner shows the agent's last message (cx-n9aa2)" + }, + { + "author": "Lawrence Chen", + "title": "cmux-tui-rust-check: the warm target stamp also names the zig version; a kept target dir is never checked" + }, + { + "author": "Leo", + "pr": 20991, + "title": "cmux-next composer: one shield family for access modes" + }, + { + "author": "Leo", + "pr": 20994, + "title": "Stats page: show permission waits, limit errors and steers per turn" + }, + { + "author": "Leo", + "pr": 20933, + "title": "Debug: chat header tools in the pane's tab row (no top bar prototype, hq-1d)" + }, + { + "author": "Lawrence Chen", + "title": "cmux-tui-rust-check: wipe a warm in-checkout cargo target when rustc -vV or its stamp changes" + }, + { + "author": "Leo", + "pr": 20796, + "title": "Agent pane: opt-in reasoning slider in the composer's reasoning menu (Debug toggle agent.reasoningSlider)" + }, + { + "author": "Leo", + "pr": 20832, + "title": "Agent pane: suggested tasks card, live child rows and received results (Labs, cx-lo9yf)" + }, + { + "author": "Leo", + "pr": 20920, + "title": "cmux-tui: Update Everything updates a machine's agent CLIs and continues its chats (cx-1mbnu)" + }, + { + "author": "Leo", + "pr": 21009, + "title": "fix: a closed pane reopens in its own split" + }, + { + "author": "Lawrence Chen", + "title": "Home live run join: review fixes (cx-kdm25)" + }, + { + "author": "Leo", + "pr": 21070, + "title": "cmux-tui: send the start surface's workspace to acpmux" + }, + { + "author": "Lawrence Chen", + "title": "cmux-tui-rust-check: stop the test run's leaked processes before reruns and doc tests (cx-leo45)" + }, + { + "author": "Leo", + "pr": 21031, + "title": "Agent composer: plain top strip leaves no stray hairline above the card's corners" + }, + { + "author": "Lawrence Chen", + "title": "Home live run: a view that joins mid-run reads the run's rows and shows the reply segments the owner already freed (cx-kdm25)" + }, + { + "author": "Leo", + "pr": 21100, + "title": "cmux-tui: cmux status wait (cx-6so.14)" + }, + { + "author": "Lawrence Chen", + "title": "test(home): a view that joins a Chief's run after two reply segments ended shows the whole reply at once, and the reply lands with no move (cx-kdm25, red)" + }, + { + "author": "Leo", + "pr": 21085, + "title": "acpmux: count a fork's copied turns once in the stats totals (hq#1920)" + }, + { + "author": "Lawrence Chen", + "title": "Sidebar: a scroll frame does less main-thread work at 1,000 workspaces" + }, + { + "author": "Lawrence Chen", + "title": "sidebar perf bench: clean method (one app at a time, same frame) and a host floor app" + }, + { + "author": "Leo", + "pr": 20826, + "title": "cmux NEXT: /btw side sessions share one right pane; pane relay allows _acpmux/btw" + }, + { + "author": "Leo", + "pr": 20787, + "title": "CmuxNext: reasoning menu drawn as a native menu" + }, + { + "author": "Leo", + "pr": 20972, + "title": "cmux NEXT: Allow once / Deny on agent chat approval banners (cx-kz6m0.2)" + }, + { + "author": "Leo", + "pr": 21062, + "title": "webviews tests: stop the Vite a vp dev server started" + }, + { + "author": "Austin Wang", + "pr": 21032, + "title": "perf: add a browser engine bench for tagged builds" + }, + { + "author": "Lawrence Chen", + "title": "cx-frn2y follow-up: enable/disable Channels succeed and write nothing when nothing changes; Open Channels (home.channels) needs the new homeChannelsEnabled context fact, so it is hidden and refused while Channels is off (hq-6d decisions 3, 4)" + }, + { + "author": "Lawrence Chen", + "title": "cx-frn2y follow-up: red behavior test: CLI enable/disable Channels succeed when nothing changes; Open Channels hidden (palette, CLI) while Channels is off" + }, + { + "author": "Lawrence Chen", + "title": "ci: rust-check review fixes: the PTY sampler has no stdout and dies with the step; nextest extracts beside its final path; rerun_notes" + }, + { + "author": "Leo", + "pr": 20976, + "title": "acpmux: one computer use display per workspace (cx-ncc.5)" + }, + { + "author": "Lawrence Chen", + "title": "ci: cmux-tui-rust-check reports the macOS PTY peak of the full run (cx-leo45)" + }, + { + "author": "Leo", + "pr": 21087, + "title": "cmux NEXT: Terminal adds toggle keeps the header's other buttons right" + }, + { + "author": "Lawrence Chen", + "title": "cx-frn2y: settings page strings regenerated on the merged head (gen-strings on a Freestyle VM; defaults snapshot unchanged)" + }, + { + "author": "Leo", + "pr": 21082, + "title": "cmux-tui tests: a status owner pid reused while the daemon was down clears only the old owner (cx-6so.13)" + }, + { + "author": "Lawrence Chen", + "title": "cx-frn2y: settings schema and MDM exports regenerated on the merged head (step 321a736b7bd6bfae4b7d7353; action exports unchanged, step af9794c4868afda3e9caf013)" + }, + { + "author": "Lawrence Chen", + "title": "ci: cmux-tui-rust-check tests run under cargo-nextest; a failed test reruns once alone and passes as FLAKY (named), or stays red" + }, + { + "author": "Leo", + "pr": 21058, + "title": "fix(acpmux): login env refresh never drops an edit or mislabels the cache (cx-6so.22)" + }, + { + "author": "Leo", + "pr": 21089, + "title": "fix: the suggested tasks tunable is nonisolated like its struct (cx-lo9yf)" + }, + { + "author": "Leo", + "pr": 20932, + "title": "cmux-tui: archives keep a 2 GB byte budget, oldest screens first (cx-gzh.4.4)" + }, + { + "author": "Lawrence Chen", + "title": "cmux-tui: tab_slot lives under tab_strip (mux.rs stays as it was; cx-d1xb8)" + }, + { + "author": "Lawrence Chen", + "title": "cx-frn2y: KeyboardLayoutObserver class and init are public in CmuxNextActions" + }, + { + "author": "Lawrence Chen", + "title": "cx-frn2y: KeyboardLayoutObserver moves CmuxNextApp -> CmuxNextActions (move only; public class and init) so CmuxNextApp stays under its size cap after the tip merge" + }, + { + "author": "Leo", + "pr": 20863, + "title": "cmux NEXT: Debug toggle turns on suggested tasks for agents (cx-lo9yf)" + }, + { + "author": "Lawrence Chen", + "title": "cmux-tui: review fixes for cx-d1xb8 (a failed reattach keeps the slot, no dead field write)" + }, + { + "author": "Lawrence Chen", + "title": "cmux-tui: Reopen Closed creates a tab at its old index in one change (cx-d1xb8)" + }, + { + "author": "Lawrence Chen", + "title": "cmux-next: color-transition-e2e runs the fast theme series three times (cx-3rf4z)" + }, + { + "author": "Lawrence Chen", + "title": "cmux-next: color fade overlays reach the screen opaque before the change (resident image, own commit), so no frame shows the new colors bare (cx-3rf4z)" + }, + { + "author": "Lawrence Chen", + "title": "test(home): measure the Chief bubble before the step's final frame, so a line that leaves at the final frame fails the hand-off check (cx-zz30r)" + }, + { + "author": "Leo", + "pr": 21080, + "title": "test: SplitPaneGridFitTests waits for launch to land its first workspace" + }, + { + "author": "Austin Wang", + "pr": 21078, + "title": "web: say how to try each v0.65.2 changelog feature" + }, + { + "author": "Lawrence Chen", + "title": "cmux-next browser: announce the emulation input scale as soon as the metrics call answers (cx-mogig)" + }, + { + "author": "Lawrence Chen", + "title": "cx-frn2y: home-channels-entry.py passes cua-driver its capture id for a pixel click; without a pixel context it clicks through the app's mouse event path and says so (job 1015-063229-fa032f)" + }, + { + "author": "Lawrence Chen", + "title": "cmux-next: color-transition-e2e measures frame steps per 60 Hz frame (the recorder's main-thread gaps span several frames) (cx-3rf4z)" + }, + { + "author": "Lawrence Chen", + "title": "cx-frn2y: home-channels-entry.py clears a partial palette query with Delete, not Cmd-A (Cmd-A opens the palette's Tabs page, job 1015-062807-e251cc)" + }, + { + "author": "Leo", + "pr": 21045, + "title": "cmux-next: agents_events long-poll MCP tool and cmux agents events (cx-ncc.97)" + }, + { + "author": "Lawrence Chen", + "title": "cx-frn2y: home-channels-entry.py types the palette query with cua-driver type_text into the front app (a foreground key to the main window closed the palette, job 1015-060719-5afd4d); prints which input path typed and pressed Return" + }, + { + "author": "Leo", + "pr": 21077, + "title": "test: font zoom debug test waits for launch to finish" + }, + { + "author": "Lawrence Chen", + "title": "cmux-next settings: Color Changes page group back in the schema export (fleet export step on 485b72ee8020; dropped by cded94aa34e4's stale regeneration) (cx-3rf4z)" + }, + { + "author": "Lawrence Chen", + "title": "Home live run: the activity line keeps its row until the reply took the Chief bubble's place, then closes on the next display frame, so the bubble never moves before the hand-off (cx-zz30r)" + }, + { + "author": "Lawrence Chen", + "title": "test(home): a Chief's bubble does not move between the reply step's final frame and the reply's hand-off (cx-zz30r, red)" + }, + { + "author": "Leo", + "pr": 20516, + "title": "scripts(cmux-next): measure whether each surface paints its final layout on frame 1" + }, + { + "author": "Lawrence Chen", + "title": "free tier tests: no as_ref on a &Path (clippy)" + }, + { + "author": "Leo", + "pr": 21023, + "title": "acpmux: stats roll spend and working time up by git branch (hq#1920)" + }, + { + "author": "Leo", + "pr": 21067, + "title": "cmux-tui: agent message unsend and pump edge cases (agent messaging 4b)" + }, + { + "author": "Lawrence Chen", + "title": "fix(cmux-next): the omnibar's neutral selected row steps 0.105 over the dark card, the reference's own step (cx-d0d.101)" + }, + { + "author": "Leo", + "pr": 20917, + "title": "feat(acpmux): _acpmux/process/tail for Claude Code background shells" + }, + { + "author": "Lawrence Chen", + "title": "cx-frn2y: home-channels-entry.py types into the palette with real keys through the HID queue (cua-driver foreground); a background post to the pid never reached the palette panel (job 1015-060437-3b4e3b)" + } + ], + "shortVersion": "1.0.0-nightly.3886569630501", + "summary": [ + { + "group": "new", + "title": "Stream ACP tool progress" + }, + { + "group": "new", + "title": "Omnibar at 28 pt / 14 pt at every density, its own card color and 12 pt card corners" + }, + { + "group": "new", + "title": "Add a browser engine bench for tagged builds" + }, + { + "group": "fixed", + "title": "Workspace hint chips show the digit Cmd-digit selects" + }, + { + "group": "fixed", + "title": "The line-batch helper's public signature needs a public Foundation import" + }, + { + "group": "fixed", + "title": "Refresh workspace names after rename" + }, + { + "group": "changed", + "title": "Chief hands: sandbox review fixes, the lane's own sandbox image, gateway P2s" + }, + { + "group": "changed", + "title": "Chief hands: agent sessions end their model access; sandboxes use a hands-only Freestyle…" + } + ], + "version": 1 + }, + { + "build": "3850073942601", + "changes": [], + "date": "2026-10-14", + "head": "692a32616bd6324ca205b90d7b673ee6d32cdce9", + "highlights": [], + "items": [ + { + "author": "Leo", + "pr": 20342, + "title": "cmux-next: sidebar rows show once the sidebar has a size; hover card dwell tests on a manual clock" + }, + { + "author": "Lawrence Chen", + "title": "Passwords: the reveal sheet is left out of screen capture and screen sharing (cx-bkyn9)" + }, + { + "author": "Lawrence Chen", + "title": "debug.passwords_reveal: show the Passwords reveal sheet with a fixture secret (red for cx-bkyn9)" + }, + { + "author": "Leo", + "pr": 20338, + "title": "CmuxNext: inject the clock into the daily background so next-day art is deterministic" + }, + { + "author": "Lawrence Chen", + "title": "acpmux: gate claude_auth_env tests on unix (cx-5mbby follow-up)" + }, + { + "author": "Leo", + "pr": 20216, + "title": "cx-98s: keep New Tab Cmd-T under the p95 budget" + }, + { + "author": "lawrencecchen", + "title": "acpmux codex bridge: review fixes for the web mode rule (cx-2v2cn)" + }, + { + "author": "lawrencecchen", + "title": "acpmux: Codex is the in-process bridge; authenticated Web takes any bridge mode (cx-2v2cn, cx-3ttyg)" + }, + { + "author": "Lawrence Chen", + "title": "cmux-tui-core: snapshot socket tests follow the 10 MB scrollback default (cx-xbj8j)" + } + ], + "shortVersion": "1.0.0-nightly.3850073942601", + "summary": [ + { + "group": "changed", + "title": "Inject the clock into the daily background so next-day art is deterministic" + } + ], + "version": 1 + }, + { + "build": "3849738712201", + "changes": [], + "date": "2026-10-14", + "head": "6ccb15b252dccd76239fb548d04667c222996839", + "highlights": [], + "items": [ + { + "author": "Leo", + "pr": 20330, + "title": "Agent chat: steps read as one list; a thought shows in full" + }, + { + "author": "Lawrence Chen", + "title": "cmux-next: opaque overlays draw the separator hairline, not a full-text-color rim" + }, + { + "author": "Leo", + "pr": 20344, + "title": "scripts: restore journey counts page reports only from the reopened app" + }, + { + "author": "Leo", + "pr": 20212, + "title": "fix(cmux-next): restore debug quit fixture teardown (cx-qaay)" + }, + { + "author": "Leo", + "pr": 20214, + "title": "feat: add viewer empty state gallery coverage (cx-4oa)" + }, + { + "author": "Leo", + "pr": 20332, + "title": "test: run the matrix's sidebar-order cases on the app's placement (cx-rq6i5)" + }, + { + "author": "Leo", + "pr": 20321, + "title": "fix(ci): refuse stale cmux-next generator inputs (no bead)" + }, + { + "author": "Leo", + "pr": 20313, + "title": "fix(next): a started chat's model picker keeps its harness" + }, + { + "author": "Lawrence Chen", + "title": "Browser profiles: keep the app's delete path unchanged; CmuxNextApp is at its size cap (cx-dwg.10)" + }, + { + "author": "Lawrence Chen", + "title": "skills/cmux-browser: agents cannot delete browser profiles, only a person (cx-dwg.10)" + }, + { + "author": "Lawrence Chen", + "title": "Browser profiles: only a person deletes one; agents, scripts and the CLI are refused (cx-dwg.10)" + }, + { + "author": "Lawrence Chen", + "title": "test(cmux-tui-core): only the proved app deletes a browser profile over the socket (red) (cx-dwg.10)" + } + ], + "shortVersion": "1.0.0-nightly.3849738712201", + "summary": [ + { + "group": "fixed", + "title": "A started chat's model picker keeps its harness" + }, + { + "group": "changed", + "title": "Agent chat: steps read as one list; a thought shows in full" + }, + { + "group": "changed", + "title": "Opaque overlays draw the separator hairline, not a full-text-color rim" + }, + { + "group": "changed", + "title": "Skills/cmux-browser: agents cannot delete browser profiles, only a person" + }, + { + "group": "changed", + "title": "Browser profiles: only a person deletes one; agents, scripts and the CLI are refused" + } + ], + "version": 1 + }, + { + "build": "3849484438101", + "changes": [], + "date": "2026-10-14", + "head": "5ba6622d0d329b8a2a6251731c0fcd358405b6bd", + "highlights": [], + "items": [ + { + "author": "Leo", + "pr": 20318, + "title": "fix(next): a fork or Continue in… opens in its own tab; the chat stays" + }, + { + "author": "Leo", + "pr": 20317, + "title": "CmuxNext: one surface edge on webview panes (no inner border)" + }, + { + "author": "Leo", + "pr": 20303, + "title": "fix(cx-9ah60): sequence agent chat bottom stack without overlap" + }, + { + "author": "Leo", + "pr": 20323, + "title": "Browser: relaunched Chromium tabs restore their own back list and scroll" + }, + { + "author": "Leo", + "pr": 20213, + "title": "cmux-next: web popups cast the native popup shadow; classic New Tab suggestions are menu rows (coherence pass 2)" + }, + { + "author": "Leo", + "pr": 20121, + "title": "CmuxNext: one container level and consistent edge padding (batch 1)" + } + ], + "shortVersion": "1.0.0-nightly.3849484438101", + "summary": [ + { + "group": "fixed", + "title": "A fork or Continue in… opens in its own tab; the chat stays" + }, + { + "group": "fixed", + "title": "Sequence agent chat bottom stack without overlap" + }, + { + "group": "changed", + "title": "One surface edge on webview panes (no inner border)" + }, + { + "group": "changed", + "title": "Web popups cast the native popup shadow; classic New Tab suggestions are menu rows…" + }, + { + "group": "changed", + "title": "One container level and consistent edge padding (batch 1)" + } + ], + "version": 1 + }, + { + "build": "3849033484801", + "changes": [], + "date": "2026-10-14", + "head": "ee5808950badf8d4386bedd36b300e93aff21629", + "highlights": [], + "items": [ + { + "author": "Leo", + "pr": 20320, + "title": "cmux-next: the sidebar row's status marks are crisp, badge-tall and on the title's line (cx-b8idn)" + }, + { + "author": "Leo", + "pr": 20301, + "title": "cx-8dw2g: Agent Activity loads the shared stylesheet; guard every internal page's font; design pass" + }, + { + "author": "Leo", + "pr": 20310, + "title": "cmux-next: a restored terminal whose attach fails retries by itself and says Restoring (cx-wwtam)" + }, + { + "author": "Leo", + "pr": 20148, + "title": "cx-wyh9f: the New Tab card is the agent composer's: field, model and Send, then the project row" + }, + { + "author": "Leo", + "pr": 20326, + "title": "test(webviews): peer-chat test loads the dev server before it times the chat (cx-c1tsn)" + }, + { + "author": "Leo", + "pr": 20306, + "title": "cmux-next: a decided quit ends within 15 s of its engine stop (cx-ccjnn)" + }, + { + "author": "Leo", + "pr": 20291, + "title": "fix: the profile menu's rows sit at the plain menu inset" + }, + { + "author": "Leo", + "pr": 20297, + "title": "cx-5dvig: sidebar update cards fit, share the composer's surface; popup adds only the rest, no arrow" + }, + { + "author": "Leo", + "pr": 20315, + "title": "CmuxNext: sidebar rows tile so hover moves row to row with no flicker" + } + ], + "shortVersion": "1.0.0-nightly.3849033484801", + "summary": [ + { + "group": "fixed", + "title": "The profile menu's rows sit at the plain menu inset" + }, + { + "group": "changed", + "title": "The sidebar row's status marks are crisp, badge-tall and on the title's line" + }, + { + "group": "changed", + "title": "Agent Activity loads the shared stylesheet; guard every internal page's font; design pass" + }, + { + "group": "changed", + "title": "A restored terminal whose attach fails retries by itself and says Restoring" + }, + { + "group": "changed", + "title": "The New Tab card is the agent composer's: field, model and Send, then the project row" + }, + { + "group": "changed", + "title": "A decided quit ends within 15 s of its engine stop" + }, + { + "group": "changed", + "title": "Sidebar update cards fit, share the composer's surface; popup adds only the rest, no arrow" + }, + { + "group": "changed", + "title": "Sidebar rows tile so hover moves row to row with no flicker" + } + ], + "version": 1 + }, + { + "build": "3848536091801", + "changes": [], + "date": "2026-10-14", + "head": "3de2039f4b4d1b60f8340aece42ec68db44a7096", + "highlights": [], + "items": [ + { + "author": "Leo", + "pr": 20307, + "title": "cmux-next: the workspace hover card's icons are labeled and on its grid (cx-y9ua3)" + }, + { + "author": "Leo", + "pr": 20276, + "title": "webviews: fix feat-cmux-next's three react-apps-check base reds (no bead)" + }, + { + "author": "Leo", + "pr": 20316, + "title": "fix(next): an action's --session argument reaches the app; cmux agent open SESSION" + }, + { + "author": "Leo", + "pr": 20222, + "title": "Browser: relaunched tabs restore WebKit's own back list and scroll" + } + ], + "shortVersion": "1.0.0-nightly.3848536091801", + "summary": [ + { + "group": "fixed", + "title": "An action's --session argument reaches the app; cmux agent open SESSION" + }, + { + "group": "changed", + "title": "The workspace hover card's icons are labeled and on its grid" + } + ], + "version": 1 + }, + { + "build": "3848245054701", + "changes": [], + "date": "2026-10-13", + "head": "6c70782d07d980d3102952964bc4d6c316095383", + "highlights": [], + "items": [ + { + "author": "Leo", + "pr": 20311, + "title": "cmux-next: a New Tab page's hover card shows no black thumbnail or chrome://newtab line" + }, + { + "author": "github-actions[bot]", + "title": "chore(next): base autofix at ba760d6a54db" + } + ], + "shortVersion": "1.0.0-nightly.3848245054701", + "summary": [ + { + "group": "changed", + "title": "A New Tab page's hover card shows no black thumbnail or chrome://newtab line" + } + ], + "version": 1 + }, + { + "build": "3847849364801", + "changes": [], + "date": "2026-10-13", + "head": "ba760d6a54dbbf9876c1f85382035132c5f3e660", + "highlights": [], + "items": [ + { + "author": "Lawrence Chen", + "title": "feat(cmux-next): the React App Store page uses the daemon's panels, Hide/Show with a click, Open as a host action (cx-hnmbt.13)" + }, + { + "author": "Leo", + "pr": 20296, + "title": "test: the probe's history-search case gets room for its tree keys (no bead)" + }, + { + "author": "Lawrence Chen", + "title": "style(cmux-tui): rustfmt the Apps page panels test (cx-hnmbt.13)" + }, + { + "author": "Leo", + "pr": 20294, + "title": "fix: workspace row hover fades its buttons and fill both ways in place" + }, + { + "author": "Lawrence Chen", + "title": "feat(cmux-tui): the daemon serves the App Store's installed-app panels to every page (cx-hnmbt.13)" + }, + { + "author": "Lawrence Chen", + "title": "test(cmux-tui): the Apps page reads grants, logs and icons and changes apps only for the person (red, cx-hnmbt.13)" + } + ], + "shortVersion": "1.0.0-nightly.3847849364801", + "summary": [ + { + "group": "fixed", + "title": "Workspace row hover fades its buttons and fill both ways in place" + } + ], + "version": 1 + }, + { + "build": "3847394302701", + "changes": [], + "date": "2026-10-13", + "head": "a020dfe5b4ec71bde7d6864f22435f22e30b2081", + "highlights": [], + "items": [ + { + "author": "Leo", + "pr": 20290, + "title": "ci: core model matrix in the cmux NEXT fast tier (cx-gkyi1)" + }, + { + "author": "Lawrence Chen", + "title": "fix(cmux-next): the Swift App Store is the default again; React stays behind apps.store.surface (cx-hnmbt.13)" + }, + { + "author": "Leo", + "pr": 20200, + "title": "Agent chats: agents run the app's cmux and reach the app (cx-c6xdh)" + }, + { + "author": "Leo", + "pr": 20253, + "title": "test: run the shared matrix's headless cases on the daemon core (cx-gkyi1)" + }, + { + "author": "Lawrence Chen", + "title": "fix(cmux-next): the React App Store page obeys DisabledFeatures apps (cx-hnmbt.11)" + }, + { + "author": "Lawrence Chen", + "title": "feat(cmux-next): the React App Store page is the default; FirstPartyPages is a struct (cx-hnmbt.11, cx-hnmbt.10)" + }, + { + "author": "Lawrence Chen", + "title": "fix(cmux-tui): page listener review: a bound listener answers the origins it admits, page ids from a lowercased Origin (cx-hnmbt.10)" + }, + { + "author": "Lawrence Chen", + "title": "feat(cmux-tui): the app's page listener admits every first-party page origin (cx-hnmbt.10)" + }, + { + "author": "Lawrence Chen", + "title": "test(cmux-tui): the page listener admits every app page origin and no other (red, cx-hnmbt.10)" + } + ], + "shortVersion": "1.0.0-nightly.3847394302701", + "summary": [ + { + "group": "changed", + "title": "Agent chats: agents run the app's cmux and reach the app" + } + ], + "version": 1 + }, + { + "build": "3846537638701", + "changes": [], + "date": "2026-10-13", + "head": "241c7c219e4a67d8d7d9d8b615e12f0d5be5005c", + "highlights": [], + "items": [ + { + "author": "Lawrence Chen", + "title": "fix(cmux-next): page relay events review: resync after a replaced relay or a resubscribe, a failed subscribe keeps the calls (cx-hnmbt.9)" + }, + { + "author": "Lawrence Chen", + "title": "feat(cmux-tui): page relays hear their page's events; History refreshes live on a closed workspace (cx-hnmbt.9)" + }, + { + "author": "Lawrence Chen", + "title": "test(cmux-tui): the History page relay hears a closed workspace as history-changed (red, cx-hnmbt.9)" + } + ], + "shortVersion": "1.0.0-nightly.3846537638701", + "summary": [ + { + "group": "fixed", + "title": "Page relay events review: resync after a replaced relay or a resubscribe, a failed…" + } + ], + "version": 1 + }, + { + "build": "3845050428001", + "changes": [], + "date": "2026-10-13", + "head": "9f25cc8d94abf4113897fddf828298ec50b43c03", + "highlights": [], + "items": [ + { + "author": "Lawrence Chen", + "title": "fix(webviews): History page renders daemon entries: at_ms arrives as a decimal string (cx-hnmbt.8)" + }, + { + "author": "Lawrence Chen", + "title": "fix(cmux-tui): page router review: App Store changes need a native sheet, one gesture per call (cx-hnmbt.8.1, cx-hnmbt.8.2)" + }, + { + "author": "Lawrence Chen", + "title": "feat(cmux-tui): daemon page router v1: per-page identity, apps.* routing, raw event frames (cx-hnmbt.8.1, cx-hnmbt.8.2, cx-hnmbt.8.3)" + }, + { + "author": "Lawrence Chen", + "title": "test(cmux-tui): page router behavior tests (red, cx-hnmbt.8.1, cx-hnmbt.8.2, cx-hnmbt.8.3)" + } + ], + "shortVersion": "1.0.0-nightly.3845050428001", + "summary": [], + "version": 1 + }, + { + "build": "3843253865201", + "changes": [], + "date": "2026-10-13", + "head": "3890d58f83bfa481f591862a7a8c29ec19375918", + "highlights": [], + "items": [ + { + "author": "Lawrence Chen", + "title": "cmux-next Home: home-scale-change.py starts the rig's vdisplay with --detach --owner and stops it by its pid" + }, + { + "author": "Lawrence Chen", + "title": "cmux-next Home: vendor MessagesLab pin 28752cc (main 6b0f80f): text balloon widths on whole device pixels (cx-mp1ec)" + } + ], + "shortVersion": "1.0.0-nightly.3843253865201", + "summary": [], + "version": 1 + }, + { + "build": "3842416936901", + "changes": [], + "date": "2026-10-13", + "head": "fafdfbdb1eb5a0c5d732d90f6bf374c05b4d60d5", + "highlights": [], + "items": [ + { + "author": "Lawrence Chen", + "title": "Revert \"optchat-host: compactor effort high\" (cx-7ssql): slower and dearer" + }, + { + "author": "Lawrence Chen", + "title": "cmux-next Channels: in-app tab connects again; bundled owners serve pages (cx-hnmbt.6, cx-hnmbt.7)" + }, + { + "author": "Lawrence Chen", + "title": "cmux-tui: red behavior test, an owner started from the app bundle serves its pages without CMUX_TUI_PAGES_DIR (cx-hnmbt.7)" + }, + { + "author": "github-actions[bot]", + "title": "chore(next): base autofix at f45c4b9d4ebe" + }, + { + "author": "Lawrence Chen", + "title": "fix(cmux-tui,cmux-next,webviews): review fixes for ws-listen and the page credential (cx-hnmbt.5, cx-hnmbt.4)" + }, + { + "author": "Lawrence Chen", + "title": "style(cmux-tui): rustfmt module order (cx-hnmbt.5)" + }, + { + "author": "Lawrence Chen", + "title": "fix(cmux-tui): clippy redundant clone of the minted page listener token (cx-hnmbt.5)" + }, + { + "author": "Lawrence Chen", + "title": "feat(cmux-tui,cmux-next): ws-listen opens the page listener on a running owner; the app recovers old owners (cx-hnmbt.5)" + }, + { + "author": "Lawrence Chen", + "title": "test(cmux-tui): a running owner without its page listener opens one on ws-listen (red, cx-hnmbt.5)" + } + ], + "shortVersion": "1.0.0-nightly.3842416936901", + "summary": [ + { + "group": "changed", + "title": "In-app tab connects again; bundled owners serve pages" + } + ], + "version": 1 + }, + { + "build": "3841787349801", + "changes": [], + "date": "2026-10-13", + "head": "f45c4b9d4ebeba7746bbec1cdbffb974215568df", + "highlights": [], + "items": [ + { + "author": "Lawrence Chen", + "title": "test(cmux-tui): a page credential is single use; an open page learns that the app signed in (cx-hnmbt.4)" + }, + { + "author": "Lawrence Chen", + "title": "fix(cmux-tui,cmux-next,webviews): page credentials are single use and apart from pairings; decode expires_in; sign-in reaches the page (cx-hnmbt.4)" + }, + { + "author": "Lawrence Chen", + "title": "chore(cmux-next): page-credential-v1 is an optional daemon capability (cx-hnmbt.4)" + }, + { + "author": "Lawrence Chen", + "title": "fix(cmux-tui): no new unwrap in the page credential issue; brain-lease test ignores the brain's own socket (cx-hnmbt.4)" + }, + { + "author": "Lawrence Chen", + "title": "style(cmux-tui): rustfmt (cx-hnmbt.4)" + }, + { + "author": "Lawrence Chen", + "title": "fix(cmux-tui,webviews,cmux-next): only a paired page credential carries the person's Cloud lease; review fixes (cx-hnmbt.4)" + }, + { + "author": "Lawrence Chen", + "title": "feat(webviews): Channels shows the person's Cloud conversations through the daemon, merged with local (cx-hnmbt.4)" + }, + { + "author": "Lawrence Chen", + "title": "fix(cmux-tui): the WebSocket refusal test follows ws-cloud-conversations-v1; rustfmt (cx-hnmbt.4)" + }, + { + "author": "Lawrence Chen", + "title": "feat(cmux-tui): ws-cloud-conversations-v1: the person's authenticated page uses the app's Cloud lease through the daemon (cx-hnmbt, cmux#13742)" + }, + { + "author": "Lawrence Chen", + "title": "test(cmux-tui): the person's page gets cloud conversations through the daemon (red, cx-hnmbt)" + } + ], + "shortVersion": "1.0.0-nightly.3841787349801", + "summary": [], + "version": 1 + }, + { + "build": "3840460186801", + "changes": [], + "date": "2026-10-13", + "head": "ba17a24d83fdbcf30d1ea30753091339c8c7dae7", + "highlights": [], + "items": [ + { + "author": "Leo", + "pr": 20230, + "title": "cmux-next: three cmux-next checks base reds (SIGPIPE sockets, test notification centers, scrollbar exceptions)" + }, + { + "author": "Leo", + "pr": 20267, + "title": "cmux-next: the opacity slider reload test waits a second, not a drag's 60 ms (cx-7l2nc)" + }, + { + "author": "github-actions[bot]", + "title": "chore(next): base autofix at 8b2dc4b5e999" + }, + { + "author": "Lawrence Chen", + "title": "fix(cmux-tui-core): page files keep the crash ratchet flat (no unwrap tokens) (cx-hnmbt.2)" + }, + { + "author": "Lawrence Chen", + "title": "fix(cmux-next): credential host verb uses the pages JSONValue; nonisolated file model (cx-hnmbt.2)" + }, + { + "author": "Lawrence Chen", + "title": "fix(cx-hnmbt.2): review findings: exact pairing ids, credential file checks, retry reason, socket leaks, 64 KiB heads" + }, + { + "author": "Lawrence Chen", + "title": "refactor(cmux-next): page listener arguments in their own file; keep DaemonLauncher and DaemonService at their size (cx-hnmbt.2)" + }, + { + "author": "Lawrence Chen", + "title": "feat(cmux-next): app pages on the daemon WebSocket; Approve sheet for browser pairing; delete the Swift Home provider (cx-hnmbt.2)" + }, + { + "author": "Lawrence Chen", + "title": "feat(webviews): Channels page connects from the daemon, the app host and any browser; reconnects (cx-hnmbt.2)" + }, + { + "author": "Lawrence Chen", + "title": "feat(cmux-tui): app listener mints its credential file and serves page files (cx-hnmbt.2)" + }, + { + "author": "Lawrence Chen", + "title": "test(cmux-tui): app daemon listener mints its credential and serves pages (red, cx-hnmbt.2)" + } + ], + "shortVersion": "1.0.0-nightly.3840460186801", + "summary": [ + { + "group": "fixed", + "title": "Credential host verb uses the pages JSONValue; nonisolated file model" + } + ], + "version": 1 + }, + { + "build": "3839889218201", + "changes": [], + "date": "2026-10-13", + "head": "cb8d0f05cbe7db7ccd48636fa0f17fb93d6789d5", + "highlights": [], + "items": [ + { + "author": "Leo", + "pr": 20274, + "title": "test: the pin-cmux-tui fleet case runs as a fleet build on a PR job too (no bead)" + }, + { + "author": "Leo", + "pr": 20273, + "title": "ci(cx-v0v8k): add pane zoom motion to the cmux NEXT fast tier" + }, + { + "author": "github-actions[bot]", + "title": "chore(next): base autofix at 1531c109fcd4" + } + ], + "shortVersion": "1.0.0-nightly.3839889218201", + "summary": [], + "version": 1 + }, + { + "build": "3839629140701", + "changes": [], + "date": "2026-10-13", + "head": "1531c109fcd48aba8cc7c414e72eadb494aa20a8", + "highlights": [], + "items": [ + { + "author": "Leo", + "pr": 20190, + "title": "cmux-next: a new tab appears where it will live, in one motion; an empty terminal has no preview" + }, + { + "author": "Leo", + "pr": 20265, + "title": "test: page info fade tests wait for the fade's end, not a fixed 600 ms" + }, + { + "author": "Leo", + "pr": 20197, + "title": "Woken chat page comes back as it was left" + }, + { + "author": "Leo", + "pr": 20201, + "title": "Agent pane: a click another process posts on the permission card grants nothing (cx-ocdz)" + }, + { + "author": "Leo", + "pr": 20203, + "title": "cmux-next: zoom the Apple way; the opposite corner leaves first, the terminal resizes once" + }, + { + "author": "Leo", + "pr": 20209, + "title": "test: the secret card's first page waits out a cold module load" + }, + { + "author": "Leo", + "pr": 20271, + "title": "chore(next): defaults snapshot names tabs.toolbarButtons (no bead)" + }, + { + "author": "Lawrence Chen", + "title": "ci(cmux-next): crash ratchet on pull requests into feat-cmux-next, judged against the base" + }, + { + "author": "Lawrence Chen", + "title": "chore(cmux-next scripts): agent-pane-live.py opens the chat in the focused pane when the targeted open created nothing (cx-07ezn)" + }, + { + "author": "Leo", + "pr": 20269, + "title": "Fix base size cap: move the CLI installer out of CmuxNextApp" + }, + { + "author": "Lawrence Chen", + "title": "Agent pane: New side chat's tag is acpmux's _acpmux/side, sent by the pane (cx-jlzsf)" + }, + { + "author": "Lawrence Chen", + "title": "acpmux: Muse Code chats in All chats with `muse resume `, terminal harness (cx-exg4j)" + }, + { + "author": "Lawrence Chen", + "title": "acpmux: behavior test, Muse Code chats list and open muse resume (red) (cx-exg4j)" + }, + { + "author": "Lawrence Chen", + "title": "cmux-tui: Muse Code hooks report working / needs input / done to the terminal (cx-exg4j)" + }, + { + "author": "Lawrence Chen", + "title": "cmux-tui: behavior test, Muse Code hooks report to the muse terminal (red) (cx-exg4j)" + }, + { + "author": "Leo", + "pr": 20257, + "title": "cmux-tui: keep 10 MB of scrollback per terminal by default" + }, + { + "author": "Lawrence Chen", + "title": "optchat-chief: turns load the MCP tools eagerly, no ToolSearch (cx-7ssql)" + }, + { + "author": "Lawrence Chen", + "title": "optchat-host: compactor effort high, as the reference client (cx-7ssql)" + }, + { + "author": "Leo", + "pr": 20208, + "title": "fix: feat-cmux-next base reds in react-apps-check and cmux-next checks" + }, + { + "author": "Lawrence Chen", + "title": "cmux-next: Settings page strings for tabs.toolbarButtons" + }, + { + "author": "Lawrence Chen", + "title": "cmux-next: regenerate settings schema and MDM exports for tabs.toolbarButtons" + }, + { + "author": "Lawrence Chen", + "title": "feat(acpmux): ConnAuth, the proof each connection presented (cx-dfi1b)" + }, + { + "author": "Lawrence Chen", + "title": "test(acpmux): a remote connection says its authentication proof (red)" + }, + { + "author": "Lawrence Chen", + "title": "fix(cx-d0d.85): drop 3 new registry-lock unwraps in browser profile handlers" + }, + { + "author": "Lawrence Chen", + "title": "Agent pane: harness health is read from acpmux on the pane's own connection (cx-jlzsf)" + }, + { + "author": "Lawrence Chen", + "title": "cmux-next: FFI, CEF shim and server-helper build targets macOS 14.0 (app-ffi release for the macOS 14 floor) (cx-s6wi.8)" + }, + { + "author": "Lawrence Chen", + "title": "browser: Chromium tabs show Chromium's own error pages and certificate interstitial again (cx-zjcq)" + }, + { + "author": "Lawrence Chen", + "title": "acpmux: a host watches its record with kqueue on macOS, not FSEvents (cx-ckdxf)" + } + ], + "shortVersion": "1.0.0-nightly.3839629140701", + "summary": [ + { + "group": "fixed", + "title": "Feat-cmux-next base reds in react-apps-check and cmux-next checks" + }, + { + "group": "fixed", + "title": "Drop 3 new registry-lock unwraps in browser profile handlers" + }, + { + "group": "changed", + "title": "A new tab appears where it will live, in one motion; an empty terminal has no preview" + }, + { + "group": "changed", + "title": "Woken chat page comes back as it was left" + }, + { + "group": "changed", + "title": "Agent pane: a click another process posts on the permission card grants nothing" + }, + { + "group": "changed", + "title": "Zoom the Apple way; the opposite corner leaves first, the terminal resizes once" + } + ], + "version": 1 + } +] diff --git a/webviews/src/pages/changelog/notesCheck.ts b/webviews/src/pages/changelog/notesCheck.ts new file mode 100644 index 000000000000..1c3404850a2b --- /dev/null +++ b/webviews/src/pages/changelog/notesCheck.ts @@ -0,0 +1,13 @@ +import type { ReleaseNotes } from "./types"; + +export type DefectKind = "duplicate" | "truncated" | "bead" | "internal"; + +export interface NotesDefect { + kind: DefectKind; + where: "notes" | "page (1 nightly)" | "page (10 nightlies)" | "card"; + text: string; +} + +export function checkNightlyNotes(_notes: ReleaseNotes, _previous: ReleaseNotes[]): NotesDefect[] { + return []; +} diff --git a/webviews/test/changelog-notes-check.test.ts b/webviews/test/changelog-notes-check.test.ts new file mode 100644 index 000000000000..83bb23716791 --- /dev/null +++ b/webviews/test/changelog-notes-check.test.ts @@ -0,0 +1,114 @@ +// The pre-publish check of a nightly's notes (nightly.yml check-release-notes, Leo 2026-10-18): +// what the What's New page shows for the last 1 and 10 nightlies and what the update card shows +// for the build, before the notes are uploaded. The fixture is the 50 nightlies the nightly-next +// notes index listed on 2026-10-19, as published. +import { expect, test } from "bun:test"; +import fixture from "../src/pages/changelog/fixtures/nightly-next-50.json"; +import { checkNightlyNotes } from "../src/pages/changelog/notesCheck"; +import type { ReleaseNotes, WhatsNewEntry } from "../src/pages/changelog/types"; + +const nightlies = fixture as ReleaseNotes[]; + +function at(build: string): { notes: ReleaseNotes; previous: ReleaseNotes[] } { + const index = nightlies.findIndex((n) => n.build === build); + return { notes: nightlies[index]!, previous: nightlies.slice(index + 1, index + 10) }; +} + +function digestEntry(id: string, title: string, summary = title): WhatsNewEntry { + return { id, category: "improved", title: { en: title }, summary: { en: summary } }; +} + +function withEntries(notes: ReleaseNotes, entries: WhatsNewEntry[]): ReleaseNotes { + return { ...notes, whatsNew: { ...notes.whatsNew!, entries } }; +} + +test("3917159104301 as published fails on its cut digest title; the page and card show it whole", () => { + const { notes, previous } = at("3917159104301"); + const defects = checkNightlyNotes(notes, previous); + expect(defects).toEqual([ + { + kind: "truncated", + where: "notes", + text: "Export-backdrop-art reads each entry's subject box and…", + }, + ]); +}); + +test("notes as the current pipeline writes them pass, alone and with the nine nightlies before them", () => { + const { notes, previous } = at("3917159104301"); + const fixed = withEntries(notes, [ + { ...notes.whatsNew!.entries[0]!, category: "fixed" }, + digestEntry("summary-1", "Export-backdrop-art reads each entry's subject box and exports it"), + ]); + expect(checkNightlyNotes(fixed, previous)).toEqual([]); +}); + +test("a leaked bead id, a cut title and internal work in the build's own lines fail", () => { + const { notes, previous } = at("3917159104301"); + const bad: ReleaseNotes = { + ...withEntries(notes, [ + digestEntry("summary-0", "Keep the Mac awake while agents work (cx-ab12)"), + digestEntry("summary-1", "perf-gate: a switch budget of 0 sidebar row configures"), + ]), + summary: [ + { group: "fixed", title: "Keep the Mac awake while agents work (cx-ab12)" }, + { group: "changed", title: "Tabs reopen where they were..." }, + ], + }; + const kinds = checkNightlyNotes(bad, previous).map((d) => `${d.where} ${d.kind} ${d.text}`); + expect(kinds).toContain("notes bead Keep the Mac awake while agents work (cx-ab12)"); + expect(kinds).toContain("notes internal perf-gate: a switch budget of 0 sidebar row configures"); + expect(kinds).toContain("notes truncated Tabs reopen where they were..."); +}); + +test("a reviewed entry the page would show twice, or with its title as its description, fails", () => { + const { notes, previous } = at("3917159104301"); + const twice = withEntries(notes, [ + { ...digestEntry("tabs", "Tabs reopen where they were", "Tabs reopen where they were"), category: "new" }, + { ...digestEntry("tabs-again", "Tabs reopen where they were", "After a relaunch."), category: "new" }, + ]); + const defects = checkNightlyNotes(twice, previous).map((d) => `${d.where} ${d.kind} ${d.text}`); + expect(defects).toContain("notes duplicate Tabs reopen where they were"); +}); + +test("a defect only an older nightly has is not this build's to fix", () => { + const { notes, previous } = at("3917159104301"); + const fixed = withEntries(notes, [{ ...notes.whatsNew!.entries[0]!, category: "fixed" }]); + const older = previous.map((n, i) => + i === 0 ? { ...n, highlights: [{ id: "old", title: "An old highlight cut short…", body: "" }] } : n, + ); + expect(checkNightlyNotes(fixed, older)).toEqual([]); +}); + +test("every one of the 50 published nightlies shows clean on the page and the card", () => { + for (const [index, notes] of nightlies.entries()) { + const shown = checkNightlyNotes(notes, nightlies.slice(index + 1, index + 10)).filter((d) => d.where !== "notes"); + expect([notes.build, shown]).toEqual([notes.build, []]); + } +}); + +// The nightly job runs the check as `bun scripts/cmux-next/check-release-notes.ts NOTES PREVIOUS…`. +test("the command fails with one annotation per defect, and passes clean notes", async () => { + const { mkdtempSync, writeFileSync } = await import("node:fs"); + const { tmpdir } = await import("node:os"); + const dir = mkdtempSync(`${tmpdir()}/notes-check-`); + const { notes, previous } = at("3917159104301"); + const files = [notes, ...previous].map((n) => { + const path = `${dir}/${n.build}.json`; + writeFileSync(path, JSON.stringify(n)); + return path; + }); + const script = `${import.meta.dir}/../../scripts/cmux-next/check-release-notes.ts`; + const bad = Bun.spawnSync([process.execPath, script, ...files]); + expect(bad.exitCode).toBe(1); + expect(bad.stdout.toString()).toContain( + "::error title=Release notes::3917159104301 notes: a cut title: Export-backdrop-art reads each entry's subject box and…", + ); + const fixed = withEntries(notes, [{ ...notes.whatsNew!.entries[0]!, category: "fixed" }]); + writeFileSync(files[0]!, JSON.stringify(fixed)); + const good = Bun.spawnSync([process.execPath, script, ...files]); + expect([good.exitCode, good.stdout.toString()]).toEqual([ + 0, + "3917159104301: notes, page (1 and 10 nightlies) and card read clean\n", + ]); +}); diff --git a/webviews/test/changelog-readable.test.ts b/webviews/test/changelog-readable.test.ts index eb733909acc6..cb4f53fa329d 100644 --- a/webviews/test/changelog-readable.test.ts +++ b/webviews/test/changelog-readable.test.ts @@ -4,7 +4,8 @@ // published. import { expect, test } from "bun:test"; import span from "../src/pages/changelog/fixtures/nightly-3913596493801-span.json"; -import { mergedView, readableChanges } from "../src/pages/changelog/model"; +import nightlies from "../src/pages/changelog/fixtures/nightly-next-50.json"; +import { changeItems, mergedView, readableChanges } from "../src/pages/changelog/model"; import { readableChange, shortTitle } from "../src/pages/changelog/readableChange"; import type { ReleaseNotes } from "../src/pages/changelog/types"; @@ -96,10 +97,36 @@ test("All Changes drops a change reverted in the span and reads a pull request a expect(internal).toBe(1); }); +// The 49-nightly update (3839629140701 to 3917159104301, gallery range-huge) showed "(hq#1957)" +// and "(review)" in New and All Changes, and "Feat-cmux-next base reds…" and "Compile fixes…" as +// changes a person would notice. +test("tracker and review references come off a title", () => { + expect(readableChange("cmux-next: workspace name source and revision, like tab names (hq#1957)")).toMatchObject({ + title: "Workspace name source and revision, like tab names", + internal: false, + }); + expect(readableChange("cmux-next: the stage log keeps its first 16 and newest 32 entries (review)").title).toBe( + "The stage log keeps its first 16 and newest 32 entries", + ); +}); + +test("base reds, branch names and compile fixes are internal work", () => { + expect(readableChange("fix: feat-cmux-next base reds in react-apps-check and cmux-next checks").internal).toBe(true); + expect(readableChange("cmux-next: compile fixes (replay entry shadowing Location trail content name)").internal).toBe( + true, + ); +}); + // The page reads notes published before the pipeline's rules (scripts/cmux-next/release-notes.py -// summary_entry and short_title) the same way the pipeline reads new ones. +// summary_entry and short_title) the same way the pipeline reads new ones: every subject of the +// medium span and of the 50 nightlies the gallery shows. test("the page and the pipeline read every subject of the span alike", () => { - const subjects = [...new Set((span as ReleaseNotes[]).flatMap((n) => n.changes))]; + const subjects = [ + ...new Set([ + ...(span as ReleaseNotes[]).flatMap((n) => n.changes), + ...(nightlies as ReleaseNotes[]).flatMap((n) => changeItems(n).map((c) => c.title)), + ]), + ]; const script = ` import importlib.util, json, sys spec = importlib.util.spec_from_file_location("notes", sys.argv[1]) diff --git a/webviews/test/update-ready-popover.test.tsx b/webviews/test/update-ready-popover.test.tsx index b4b0fffbc41f..ca00f27bacd3 100644 --- a/webviews/test/update-ready-popover.test.tsx +++ b/webviews/test/update-ready-popover.test.tsx @@ -105,3 +105,67 @@ test("the Updated card names the short build, says What's new in this build and const buttons = [...host.querySelectorAll("button")].map((b) => b.textContent || b.getAttribute("aria-label")); expect(buttons).toEqual(["Close", "See What's New"]); }); + +// Notes published before the pipeline's readable rules (#21873) reach the card and popup as they +// were written: a digest title cut with "…", a work-stream line, and each title repeated as its +// description (nightly 3917159104301 and earlier). The surfaces read them as the page does. +test("the popup and the card read notes published before the readable rules as the page does", async () => { + const { createRoot } = await import("react-dom/client"); + const { UpdateReadyHighlights, UpdatedCard } = await import("../src/pages/changelog/UpdateSurfaces"); + const { createStrings } = await import("../src/pages/shared/i18n"); + const table = (await import("../src/pages/changelog/generated/strings.json")).default; + const data = { + version: "1.0.0-nightly.3917159104301", + build: "3917159104301", + fromVersion: "1.0.0-nightly.3917061587901", + fromBuild: "3917061587901", + date: "2026-10-19", + source: "whatsNew" as const, + language: "en", + items: [ + { + id: "summary-2", + title: "Cmux NEXT perf-fanout: a restored New Tab page reads no tab…", + summary: "Cmux NEXT perf-fanout: a restored New Tab page reads no tab list in its pane's snapshot", + category: "improved" as const, + }, + { + id: "summary-1", + title: "Export-backdrop-art reads each entry's subject box and…", + summary: "Export-backdrop-art reads each entry's subject box and exports it", + category: "improved" as const, + }, + { + id: "summary-0", + title: "Keep the Mac awake while agents work", + summary: "Keep the Mac awake while agents work", + category: "fixed" as const, + }, + ], + moreCount: 0, + changelog: { from: "1.0.0-nightly.3917061587901", to: "1.0.0-nightly.3917159104301" }, + }; + act(() => root?.unmount()); + root = createRoot(host); + await act(async () => + root!.render( + undefined }} />, + ), + ); + const items = [...host.querySelectorAll(".wn-pop-list li")].map((li) => li.textContent); + expect(items).toEqual([ + "1Export-backdrop-art reads each entry's subject box and exports it", + "2Keep the Mac awake while agents work", + ]); + act(() => root?.unmount()); + root = createRoot(host); + await act(async () => + root!.render( + undefined }} />, + ), + ); + expect(host.querySelector(".wn-card-headline")?.textContent).toBe( + "Export-backdrop-art reads each entry's subject box and exports it", + ); + expect(host.querySelector(".wn-card-line")?.textContent).toBe("+1 more"); +}); From ad3c09e8298a2739aa794b4283299942d2fc78db Mon Sep 17 00:00:00 2001 From: Leo Li Date: Mon, 19 Oct 2026 07:08:00 +0000 Subject: [PATCH 02/26] cmux NEXT: What's New checks a nightly's notes before they publish; old notes read clean on the card MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - checkNightlyNotes (webviews/src/pages/changelog/notesCheck.ts) reads a nightly's notes as people will see them: its own lines, the What's New page for an update of 1 and of 10 nightlies, and the update card and popup. A title cut with "…", a bead id, a title shown twice or as its own description, or internal work among the machine-made lines is a defect. Only this build's defects count: the 10-nightly page is compared with the same page without it, so a defect an older nightly already published never blocks the notes after it. scripts/cmux-next/check-release-notes.ts runs it and prints one error annotation per defect. 19 of the 50 published nightlies would have failed; the current pipeline, rerun over the last 40 spans, passes all. - The update card and popup read their items as the page does (readableUpdateItems): notes published before #21873 no longer show a digest title cut with "…", a work-stream line or a title repeated as its description. - "(hq#1957)" and "(review)" come off titles on the page as they already did in the pipeline; base reds, feat-cmux-next, compile fixes and a bead id in a sentence are internal work in both. Co-Authored-By: Claude Opus 5.5 --- scripts/cmux-next/check-release-notes.ts | 23 ++- scripts/cmux-next/release-notes.py | 12 +- .../src/pages/changelog/UpdateSurfaces.tsx | 19 +-- webviews/src/pages/changelog/model.ts | 21 +++ webviews/src/pages/changelog/notesCheck.ts | 133 +++++++++++++++++- .../src/pages/changelog/readableChange.ts | 12 +- 6 files changed, 197 insertions(+), 23 deletions(-) diff --git a/scripts/cmux-next/check-release-notes.ts b/scripts/cmux-next/check-release-notes.ts index dcbbff6c9345..c690d42a82dc 100644 --- a/scripts/cmux-next/check-release-notes.ts +++ b/scripts/cmux-next/check-release-notes.ts @@ -1 +1,22 @@ -process.exit(0); +// bun scripts/cmux-next/check-release-notes.ts NOTES.json [PREVIOUS.json ...] +// +// The nightly-next pre-publish check (nightly.yml check-release-notes): reads this build's notes +// the way the What's New page (1 and 10 nightlies) and the update card will show them, and fails +// with one error annotation per defect (webviews/src/pages/changelog/notesCheck.ts). PREVIOUS are +// the nightlies published before it, newest first. +import { readFileSync } from "node:fs"; +import { annotation, checkNightlyNotes, RANGE } from "../../webviews/src/pages/changelog/notesCheck"; +import type { ReleaseNotes } from "../../webviews/src/pages/changelog/types"; + +const [path, ...previousPaths] = process.argv.slice(2); +if (!path) { + console.error("usage: check-release-notes.ts NOTES.json [PREVIOUS.json ...]"); + process.exit(2); +} +const read = (file: string) => JSON.parse(readFileSync(file, "utf8")) as ReleaseNotes; +const notes = read(path); +const previous = previousPaths.slice(0, RANGE - 1).map(read); +const defects = checkNightlyNotes(notes, previous); +for (const defect of defects) console.log(annotation(notes.build, defect)); +if (defects.length > 0) process.exit(1); +console.log(`${notes.build}: notes, page (1 and ${RANGE} nightlies) and card read clean`); diff --git a/scripts/cmux-next/release-notes.py b/scripts/cmux-next/release-notes.py index e0b56ca81f91..5fc37bff64f9 100755 --- a/scripts/cmux-next/release-notes.py +++ b/scripts/cmux-next/release-notes.py @@ -63,11 +63,11 @@ r"frame budget|osc \d+|terminal host|seed|record\w*|nightly|headless|ffi|rust|regenerate|decode|renderer|texture|" r"machine code|scene captures?|policy log|host log|force unwrap|store intent|property model|false positive|inventory|" r"boundary|on the wire|debug reports?|dom events?|keybind actions?|main actor|shims?|" - r"consumers?|metrics|review fixes)\b", re.I) + r"consumers?|metrics|review fixes|base reds?|feat-cmux-next|compile fix(?:es)?)\b", re.I) # Product names whose casing is not code. BRANDS = re.compile(r"\b(?:macOS|iOS|iPadOS|iCloud|iPhone|iPad|GitHub|YouTube|SwiftUI|WebKit|JavaScript|TypeScript|ChatGPT|OpenAI)\b") -# Code-looking subjects (dotted names, snake_case, versioned ids, backticks) are internal. -CODE_LIKE = re.compile(r"`|\b[A-Za-z_]\w*\.[A-Za-z_]\w*\b|\w_\w|\w-v\d\b|\[cx-|\b[a-z]+[A-Z]\w*|\b[A-Z][a-z]+[A-Z]\w*|\b[A-Z]{2,}(?:-[A-Z]+)+\b|\{\w+\}") +# Code-looking subjects (dotted names, snake_case, versioned ids, bead ids, backticks) are internal. +CODE_LIKE = re.compile(r"`|\b[A-Za-z_]\w*\.[A-Za-z_]\w*\b|\w_\w|\w-v\d\b|\[cx-|\bcx-[a-z0-9]{3,}|\b[a-z]+[A-Z]\w*|\b[A-Z][a-z]+[A-Z]\w*|\b[A-Z]{2,}(?:-[A-Z]+)+\b|\{\w+\}") CONVENTIONAL = re.compile(r"^(?P[A-Za-z-]+)(?:\((?P[^)]*)\))?!?:\s*(?P.+)$") AREA_PREFIX = re.compile(r"^(cmux-next(?: \w+){0,2}|cmuxnext|cmux next|acpmux|apps?|browser|gallery|release notes?|cx-[\w.]+|feed [\d.]+|cmux-tui)\s*:\s*", re.I) # "area words: rest" after the conventional type: "cmux NEXT perf-split: review: …", "cmux-next strip: …". @@ -75,9 +75,9 @@ # Work streams that measure or check the app (perf-split, perf-gate, motion-record, strip-scroll-check). INTERNAL_AREA_SHAPE = re.compile(r"^(?:perf-[\w-]+|[\w-]+-(?:check|record|gate|bench|probe)|motion-record|review|gate|base-red)$", re.I) PRODUCT_WORDS = {"cmux", "next", "cmux-next", "cmuxnext"} -# "(#123)", "(hq#45)", "(cx-abc)", "(cx-2y2 items 6, 10)", "(red)", anywhere in the subject, and a -# bead reference cut off at the end. -REFS = re.compile(r"\s*\((?:[^()]*\bcx-[\w.]+[^()]*|[\w-]*#\d+|red)\)|\s*\((?:[^()]*\b)?cx-[\w.]*$", re.I) +# "(#123)", "(hq#45)", "(cx-abc)", "(cx-2y2 items 6, 10)", "(red)", "(review)", anywhere in the +# subject, and a bead reference cut off at the end. +REFS = re.compile(r"\s*\((?:[^()]*\bcx-[\w.]+[^()]*|[\w-]*#\d+|red|review)\)|\s*\((?:[^()]*\b)?cx-[\w.]*$", re.I) def summary_entry(subject): """(group, title) for a user-facing commit subject, else None.""" diff --git a/webviews/src/pages/changelog/UpdateSurfaces.tsx b/webviews/src/pages/changelog/UpdateSurfaces.tsx index 694ec8c7119c..a809944a62eb 100644 --- a/webviews/src/pages/changelog/UpdateSurfaces.tsx +++ b/webviews/src/pages/changelog/UpdateSurfaces.tsx @@ -7,9 +7,10 @@ // - UpdateReadyHighlights (hovering the staged "Restart to Update" card): only what the card lacks // (Leo 2026-10-13; the card has Update Ready, the short version and the date): the full build, // the top three changes numbered, each a title and one line, and "See all changes", once. -// Data: UpdateHighlights (updateHighlights.ts); the host mounts these and wires the actions. +// Data: UpdateHighlights (updateHighlights.ts), read as the page reads notes (readableUpdateItems); +// the host mounts these and wires the actions. import { useId } from "react"; -import { distinctSummary } from "./model"; +import { readableUpdateItems } from "./model"; import type { Strings } from "../shared/i18n"; import type { UpdateHighlights, UpdateSurfaceActions } from "./updateHighlights"; @@ -29,8 +30,9 @@ export function UpdatedCard({ strings: Strings; actions: UpdateSurfaceActions; }) { - const [lead] = data.items; - const more = data.items.length - 1 + data.moreCount; + const items = readableUpdateItems(data.items); + const [lead] = items; + const more = items.length - 1 + data.moreCount; const titleId = useId(); return (
@@ -71,23 +73,22 @@ export function UpdateReadyHighlights({ actions: UpdateSurfaceActions; }) { const titleId = useId(); + const items = readableUpdateItems(data.items); return (
{data.version}
- {data.items.length > 0 && ( + {items.length > 0 && (
    - {data.items.map((item, index) => ( + {items.map((item, index) => (
  1. {item.title} - {item.summary && distinctSummary(item.title, item.summary) && ( - {item.summary} - )} + {item.summary && {item.summary}}
  2. ))} diff --git a/webviews/src/pages/changelog/model.ts b/webviews/src/pages/changelog/model.ts index a356e190be42..fb9260400273 100644 --- a/webviews/src/pages/changelog/model.ts +++ b/webviews/src/pages/changelog/model.ts @@ -11,6 +11,7 @@ import type { WhatsNewCategory, WhatsNewEntry, } from "./types"; +import type { UpdateHighlightItem } from "./updateHighlights"; import { readableChange, revertedSubject, shortTitle, tidyTitle, titleTail } from "./readableChange"; export const CATEGORY_ORDER: readonly WhatsNewCategory[] = ["new", "improved", "fixed", "security"]; @@ -156,6 +157,26 @@ function readableItem(item: ReleaseItem, changes: ChangeItem[], machine: boolean return { ...item, title, summary: distinctSummary(title, summary) }; } +/** The update card's and popup's items (`UpdateHighlights`, at most three) as the page reads them: + notes published before the readable rules (#21873) carry digest titles cut with "…", + work-stream lines and titles repeated as their description. A summary or appcast line is + machine-made; a What's New entry or highlight with its own id is a person's. */ +export function readableUpdateItems(items: UpdateHighlightItem[]): UpdateHighlightItem[] { + const seen = new Set(); + return items.flatMap((item) => { + const machine = /^(?:summary|appcast)-\d+$/.test(item.id); + const readable = readableItem( + { id: item.id, category: item.category, title: item.title, summary: item.summary ?? "" }, + [], + machine, + ); + const key = readable?.title.toLowerCase(); + if (!readable || !key || seen.has(key)) return []; + seen.add(key); + return [{ ...item, title: readable.title, summary: readable.summary || null }]; + }); +} + function stemOf(text: string): string { return text.replace(/[.!…\s]+$/u, "").toLowerCase(); } diff --git a/webviews/src/pages/changelog/notesCheck.ts b/webviews/src/pages/changelog/notesCheck.ts index 1c3404850a2b..4e1b9c12bac6 100644 --- a/webviews/src/pages/changelog/notesCheck.ts +++ b/webviews/src/pages/changelog/notesCheck.ts @@ -1,4 +1,17 @@ +// The pre-publish check of a nightly's notes (Leo 2026-10-18; nightly.yml check-release-notes, run +// by scripts/cmux-next/check-release-notes.ts). Before the signed notes upload, it reads them as +// people will see them: +// - the notes' own lines (What's New entries, summary lines, highlights): no title cut with "…", +// no bead id, no title twice, and no internal work among the machine-made lines; +// - the What's New page for an update of 1 nightly and of 10 (this build and the nine before it); +// - the update card and popup for this build (the three items UpdateHighlights hands them). +// On the page and card a row may not repeat its title as its description either. Only this +// build's defects count: the 10-nightly page is compared with the same page without this build, +// so a defect an older nightly already published never blocks the notes after it. +import { localized, mergedView, readableUpdateItems, type ReleaseView } from "./model"; +import { readableChange } from "./readableChange"; import type { ReleaseNotes } from "./types"; +import type { UpdateHighlightItem } from "./updateHighlights"; export type DefectKind = "duplicate" | "truncated" | "bead" | "internal"; @@ -8,6 +21,122 @@ export interface NotesDefect { text: string; } -export function checkNightlyNotes(_notes: ReleaseNotes, _previous: ReleaseNotes[]): NotesDefect[] { - return []; +/** How many nightlies the wider page check spans, this build included. */ +export const RANGE = 10; +/** Items the update card and popup get (UpdateHighlights.shownItems). */ +const CARD_ITEMS = 3; +const BEAD = /\bcx-[a-z0-9]{3,}(?:\.\d+)*\b/i; +const CUT = /(?:…|\.\.\.)$/u; + +interface Row { + title: string; + summary?: string; + /** A machine-made line, judged by the commit rules. */ + machine?: boolean; +} + +function key(text: string): string { + return text + .trim() + .replace(/[.!…\s]+$/u, "") + .toLowerCase(); +} + +/** Cut, bead and (for machine lines) internal-work defects of each row, and titles seen twice. */ +function rowDefects(where: NotesDefect["where"], rows: Row[], shown: boolean): NotesDefect[] { + const defects: NotesDefect[] = []; + const titles = new Set(); + for (const row of rows) { + const title = row.title.trim(); + const summary = (row.summary ?? "").trim(); + if (CUT.test(title)) defects.push({ kind: "truncated", where, text: title }); + if (BEAD.test(title) || BEAD.test(summary)) defects.push({ kind: "bead", where, text: title }); + if (row.machine && readableChange(title).internal) defects.push({ kind: "internal", where, text: title }); + // The page and the card show the summary beside the title; the notes may carry both alike. + const echoes = summary && (key(summary) === key(title) || key(summary).startsWith(`${key(title)} `)); + if (titles.has(key(title)) || (shown && echoes)) defects.push({ kind: "duplicate", where, text: title }); + titles.add(key(title)); + } + return defects; +} + +/** The lines the notes carry for people. */ +function noteRows(notes: ReleaseNotes, language: string): Row[][] { + const entries = notes.whatsNew?.entries ?? []; + const headline = localized(notes.whatsNew?.headline, language); + return [ + entries.map((e) => ({ title: localized(e.title, language), machine: e.id.startsWith("summary-") })), + headline ? [{ title: headline }] : [], + (notes.summary ?? []).map((line) => ({ title: line.title, machine: true })), + notes.highlights.map((h) => ({ title: h.title })), + ]; +} + +/** The page's rows: the hero and New / Improved / Fixed / Security; All Changes only for bead ids. */ +function pageDefects(where: NotesDefect["where"], view: ReleaseView): NotesDefect[] { + const rows = [view.hero, ...view.groups.flatMap((g) => g.items)].filter((i) => i !== undefined); + const changes = view.changes.filter((c) => BEAD.test(c.title)); + return [...rowDefects(where, rows, true), ...changes.map((c) => ({ kind: "bead" as const, where, text: c.title }))]; +} + +/** UpdateHighlights.pick: the What's New entries (New, Improved, Fixed, Security), else the + highlights, else the summary lines; the first three, as the card and popup read them. */ +export function cardItems(notes: ReleaseNotes, language: string): UpdateHighlightItem[] { + const firstLine = (text: string) => text.split(/\r?\n/u)[0]?.trim() || null; + const order = ["new", "improved", "fixed", "security"]; + const entries = [...(notes.whatsNew?.entries ?? [])].sort( + (a, b) => order.indexOf(a.category) - order.indexOf(b.category), + ); + const picked: UpdateHighlightItem[] = entries.length + ? entries.map((e) => ({ + id: e.id, + title: localized(e.title, language), + summary: firstLine(localized(e.summary, language)), + category: e.category, + })) + : notes.highlights.length + ? notes.highlights.map((h) => ({ id: h.id, title: h.title, summary: firstLine(h.body), category: "new" })) + : (notes.summary ?? []).map((line, index) => ({ + id: `summary-${index}`, + title: line.title, + summary: null, + category: line.group === "fixed" ? "fixed" : line.group === "new" ? "new" : "improved", + })); + return readableUpdateItems(picked.slice(0, CARD_ITEMS)); +} + +function same(a: NotesDefect, b: NotesDefect): boolean { + return a.kind === b.kind && a.text === b.text; +} + +/** Every defect of `notes` (one nightly) as people will see it; `previous` are the nightlies + published before it, newest first (the first RANGE - 1 are read). */ +export function checkNightlyNotes(notes: ReleaseNotes, previous: ReleaseNotes[], language = "en"): NotesDefect[] { + const before = previous.filter((n) => n.build !== notes.build).slice(0, RANGE - 1); + const older = pageDefects("page (10 nightlies)", mergedView(before, language)); + const defects = [ + ...noteRows(notes, language).flatMap((rows) => rowDefects("notes", rows, false)), + ...pageDefects("page (1 nightly)", mergedView([notes], language)), + ...pageDefects("page (10 nightlies)", mergedView([notes, ...before], language)).filter( + (d) => !older.some((o) => same(o, d)), + ), + ...rowDefects( + "card", + cardItems(notes, language).map((i) => ({ title: i.title, summary: i.summary ?? "" })), + true, + ), + ]; + return defects.filter((d, i) => defects.findIndex((o) => o.where === d.where && same(o, d)) === i); +} + +const LABELS: Record = { + duplicate: "a title shown twice or as its own description", + truncated: "a cut title", + bead: "a bead id", + internal: "internal work in New, Improved or Fixed", +}; + +/** One GitHub Actions error annotation. */ +export function annotation(build: string, defect: NotesDefect): string { + return `::error title=Release notes::${build} ${defect.where}: ${LABELS[defect.kind]}: ${defect.text}`; } diff --git a/webviews/src/pages/changelog/readableChange.ts b/webviews/src/pages/changelog/readableChange.ts index fbeb5ffaea5e..977fcffcb76e 100644 --- a/webviews/src/pages/changelog/readableChange.ts +++ b/webviews/src/pages/changelog/readableChange.ts @@ -61,15 +61,16 @@ const INTERNAL_WORDS = new RegExp( String.raw`frame budget|osc \d+|terminal host|seed|record\w*|nightly|headless|ffi|rust|regenerate|decode|renderer|texture|` + String.raw`machine code|scene captures?|policy log|host log|force unwrap|store intent|property model|false positive|inventory|` + String.raw`boundary|on the wire|debug reports?|dom events?|keybind actions?|main actor|shims?|` + - String.raw`consumers?|metrics|review fixes)\b`, + String.raw`consumers?|metrics|review fixes|base reds?|feat-cmux-next|compile fix(?:es)?)\b`, "i", ); /** Product names whose casing is not code. */ const BRANDS = /\b(?:macOS|iOS|iPadOS|iCloud|iPhone|iPad|GitHub|YouTube|SwiftUI|WebKit|JavaScript|TypeScript|ChatGPT|OpenAI)\b/g; -/** Code-looking text: backticks, dotted names, snake_case, versioned ids, camelCase, {placeholders}. */ +/** Code-looking text: backticks, dotted names, snake_case, versioned ids, bead ids, camelCase, + {placeholders}. */ const CODE_LIKE = - /`|\b[A-Za-z_]\w*\.[A-Za-z_]\w*\b|\w_\w|\w-v\d\b|\[cx-|\b[a-z]+[A-Z]\w*|\b[A-Z][a-z]+[A-Z]\w*|\b[A-Z]{2,}(?:-[A-Z]+)+\b|\{\w+\}/; + /`|\b[A-Za-z_]\w*\.[A-Za-z_]\w*\b|\w_\w|\w-v\d\b|\[cx-|\bcx-[a-z0-9]{3,}|\b[a-z]+[A-Z]\w*|\b[A-Z][a-z]+[A-Z]\w*|\b[A-Z]{2,}(?:-[A-Z]+)+\b|\{\w+\}/; const CONVENTIONAL = /^(?[A-Za-z-]+)(?:\((?[^)]*)\))?!?:\s*(?.+)$/; /** "area words: rest" after the conventional type: "cmux NEXT perf-split: review: …", "cmux-next strip: …". */ const LABEL = /^(?[A-Za-z][\w-]*(?: [A-Za-z][\w-]*){0,2})(?:\((?[^)]*)\))?!?:\s+(?\S.*)$/; @@ -79,8 +80,9 @@ const INTERNAL_AREA_SHAPE = const PRODUCT_WORDS = new Set(["cmux", "next", "cmux-next", "cmuxnext"]); const AREA_PREFIX = /^(cmux-next(?: \w+){0,2}|cmuxnext|cmux next|acpmux|apps?|browser|gallery|release notes?|cx-[\w.]+|feed [\d.]+|cmux-tui)\s*:\s*/i; -/** "(#123)", "(cx-abc)", "(cx-2y2 items 6, 10)", "(red)", and a bead reference cut off at the end. */ -const REFS = /\s*\((?:[^()]*\bcx-[\w.]+[^()]*|#\d+|red)\)|\s*\((?:[^()]*\b)?cx-[\w.]*$/gi; +/** "(#123)", "(hq#45)", "(cx-abc)", "(cx-2y2 items 6, 10)", "(red)", "(review)", and a bead + reference cut off at the end. */ +const REFS = /\s*\((?:[^()]*\bcx-[\w.]+[^()]*|[\w-]*#\d+|red|review)\)|\s*\((?:[^()]*\b)?cx-[\w.]*$/gi; /** The product's own label at the start of a human title: "cmux NEXT: …". */ const PRODUCT_LABEL = /^(?:cmux[- ]?next|cmuxnext)\s*:\s*/i; From 9ee94c8130ac453f08c1821cf5581ecb5dc5aa0b Mon Sep 17 00:00:00 2001 From: Leo Li Date: Mon, 19 Oct 2026 07:10:08 +0000 Subject: [PATCH 03/26] test(nightly): notes that fail their pre-publish check are not published and report Fails: nightly.yml has no check-release-notes job yet. Co-Authored-By: Claude Opus 5.5 --- tests/test_nightly_next_recovery.py | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/tests/test_nightly_next_recovery.py b/tests/test_nightly_next_recovery.py index 69f33ad6f8f7..87bf15604903 100755 --- a/tests/test_nightly_next_recovery.py +++ b/tests/test_nightly_next_recovery.py @@ -429,12 +429,13 @@ def publication(self, source, **results): jobs = ("decide", "build-nightly-ghostty-cli-helper", "build-nightly-app", "resolve-nightly-cmux-tui-client", "prepare-nightly-variant", "build-sign-notarize-nightly", "verify-signed-nightly", "verify-recovered-nightly-next", "publish-nightly", "generate-nightly-deltas", "republish-nightly-deltas", - "sign-release-notes", "publish-release-notes") + "sign-release-notes", "check-release-notes", "publish-release-notes") outcome = dict.fromkeys(jobs, "success") if source == "own": outcome["verify-recovered-nightly-next"] = "skipped" if source == "recovered": - outcome.update({"generate-nightly-deltas": "skipped", "sign-release-notes": "skipped", "publish-release-notes": "skipped"}) + outcome.update({"generate-nightly-deltas": "skipped", "sign-release-notes": "skipped", + "check-release-notes": "skipped", "publish-release-notes": "skipped"}) outcome.update(results) outputs = dict(self.OUTPUTS, **{"publish-nightly": dict(self.OUTPUTS["publish-nightly"], source=source)}) return job_runs("report-nightly-failure", outcome, outputs), job_runs("close-nightly-failure-issue", outcome, outputs) @@ -458,6 +459,22 @@ def test_a_recovered_publication_after_this_run_s_build_failed_reports(self): def test_a_recovered_publication_that_failed_its_delta_republish_reports(self): self.assertEqual(self.publication("recovered", **{"republish-nightly-deltas": "failure"}), (True, False)) + # The pre-publish check of the signed notes (scripts/cmux-next/check-release-notes.ts, Leo + # 2026-10-18): notes that fail it are not uploaded, and the failure issue names the check. + def test_notes_that_fail_their_check_are_not_published_and_report(self): + jobs = workflow()["jobs"] + check = jobs["check-release-notes"] + self.assertIn("sign-release-notes", check["needs"]) + self.assertIn("bun scripts/cmux-next/check-release-notes.ts", json.dumps(check)) + self.assertNotIn("secrets.", json.dumps(check)) + self.assertIn("check-release-notes", jobs["report-nightly-failure"]["needs"]) + publish = dict.fromkeys(jobs["publish-release-notes"]["needs"], "success") + outputs = {"decide": {"should_publish": "true", "track": "nightly-next"}, "publish-nightly": {"source": "own"}} + self.assertTrue(job_runs("publish-release-notes", publish, outputs)) + self.assertFalse(job_runs("publish-release-notes", dict(publish, **{"check-release-notes": "failure"}), outputs)) + self.assertEqual(self.publication("own", **{"check-release-notes": "failure", "publish-release-notes": "skipped"}), + (True, False)) + def test_an_already_published_recovered_build_neither_reports_nor_closes(self): # Another run published this build and owns the issue; this run's # no-op moved no marker (tag_status empty) and republished nothing. From 560691bb5aeeecb13af45a019ae74ddf9ae5bdf5 Mon Sep 17 00:00:00 2001 From: Leo Li Date: Mon, 19 Oct 2026 07:11:16 +0000 Subject: [PATCH 04/26] ci(nightly-next): check each build's notes before they publish MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit check-release-notes runs after sign-release-notes and before publish-release-notes: bun scripts/cmux-next/check-release-notes.ts reads this build's signed notes with the nine nightlies listed before it (the artifact's copy, else the published file) and fails on a title cut with "…", a bead id, a title shown twice or as its own description, or internal work in New, Improved or Fixed. publish-release-notes waits for it, and report-nightly-failure names it. No secrets in the job. ci-guards runs release-notes-items.test.sh, which no workflow ran. Co-Authored-By: Claude Opus 5.5 --- .github/workflows/ci-guards.yml | 4 +++ .github/workflows/nightly.yml | 57 ++++++++++++++++++++++++++++++--- 2 files changed, 57 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci-guards.yml b/.github/workflows/ci-guards.yml index 469b156bcff0..4700a3817c41 100644 --- a/.github/workflows/ci-guards.yml +++ b/.github/workflows/ci-guards.yml @@ -1190,6 +1190,10 @@ jobs: if: ${{ matrix.group == 'release-notary' }} run: python3 tests/test_nightly_next_release_notes_fetch.py + - name: Validate the nightly-next release notes items, summary and digest + if: ${{ matrix.group == 'release-notary' }} + run: bash scripts/cmux-next/tests/release-notes-items.test.sh + - name: Validate the nightly cmux-tui resolver (newest published tree, no wait) if: ${{ matrix.group == 'release-notary' }} run: python3 tests/test_nightly_cmux_tui_resolve.py diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml index 2f093020af29..5c9bbde4e849 100644 --- a/.github/workflows/nightly.yml +++ b/.github/workflows/nightly.yml @@ -6199,12 +6199,61 @@ jobs: path: notes/ retention-days: 7 + # The pre-publish check of the signed notes (Leo 2026-10-18): this build's notes read as the + # What's New page shows an update of 1 and of 10 nightlies, and as the update card and popup + # show them. A title cut with "…", a bead id, a title shown twice or as its own description, or + # internal work in New, Improved or Fixed fails it, and publish-release-notes waits for it + # (scripts/cmux-next/check-release-notes.ts). Only this build's defects count, so a defect an + # older nightly already published never blocks the notes after it. No secrets: it reads the + # artifact and the public feed (an unverified older file can only fail the check, never pass it). + check-release-notes: + needs: [decide, build-nightly-app, sign-release-notes, resolve-nightly-cmux-tui-client] + if: "!cancelled() && needs.decide.outputs.track == 'nightly-next' && needs.sign-release-notes.result == 'success'" + runs-on: ${{ github.repository_owner != 'manaflow-ai' && 'ubuntu-24.04' || vars.LINUX_RUNNER || 'blacksmith-4vcpu-ubuntu-2404' }} + timeout-minutes: 10 + permissions: + contents: read + env: + NIGHTLY_BUILD: ${{ needs.build-nightly-app.outputs.daemon_build }} + steps: + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + ref: ${{ needs.resolve-nightly-cmux-tui-client.outputs.build_sha }} + persist-credentials: false + sparse-checkout: | + scripts/cmux-next/check-release-notes.ts + webviews/src/pages/changelog/ + sparse-checkout-cone-mode: false + - uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7.0.0 + with: + name: release-notes + path: notes + - uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2 + with: + bun-version: "1.4.2" + - name: Check this build's notes as the page and the update card show them + run: | + set -euo pipefail + # The nine nightlies listed before this one, newest first: the artifact's copy when the + # backfill rewrote it, else the published file. + mkdir -p previous + previous=() + while IFS= read -r build; do + file="notes/$build.json" + if [ ! -f "$file" ]; then + file="previous/$build.json" + curl -fsSL --retry 3 -A "cmux-release-notes/1" -o "$file" "$NIGHTLY_NEXT_FEED_BASE/notes/$build.json" || continue + fi + previous+=("$file") + done < <(python3 -c 'import json, sys; builds = [b["build"] for b in json.load(open(sys.argv[1]))["builds"] if b["build"] != sys.argv[2]]; print("\n".join(builds[:9]))' notes/index.json "$NIGHTLY_BUILD") + bun scripts/cmux-next/check-release-notes.ts "notes/$NIGHTLY_BUILD.json" "${previous[@]}" + publish-release-notes: - needs: [decide, publish-nightly, sign-release-notes, resolve-nightly-cmux-tui-client] + needs: [decide, publish-nightly, sign-release-notes, check-release-notes, resolve-nightly-cmux-tui-client] concurrency: group: release-publish-${{ needs.decide.outputs.release_tag }} cancel-in-progress: false - if: "!cancelled() && needs.decide.outputs.track == 'nightly-next' && needs.publish-nightly.result == 'success' && needs.publish-nightly.outputs.already_published != 'true' && needs.publish-nightly.outputs.refused != 'true' && needs.sign-release-notes.result == 'success'" + if: "!cancelled() && needs.decide.outputs.track == 'nightly-next' && needs.publish-nightly.result == 'success' && needs.publish-nightly.outputs.already_published != 'true' && needs.publish-nightly.outputs.refused != 'true' && needs.sign-release-notes.result == 'success' && needs.check-release-notes.result == 'success'" environment: ${{ needs.decide.outputs.environment }} runs-on: ${{ github.repository_owner != 'manaflow-ai' && 'ubuntu-24.04' || vars.LINUX_RUNNER || 'blacksmith-4vcpu-ubuntu-2404' }} timeout-minutes: 10 @@ -6404,7 +6453,7 @@ jobs: # published build whose notes jobs did not both succeed is reported too # (run 37526646874 published with its notes job cancelled and no alarm). report-nightly-failure: - needs: [decide, build-nightly-ghostty-cli-helper, build-nightly-app, resolve-nightly-cmux-tui-client, prepare-nightly-variant, build-sign-notarize-nightly, verify-signed-nightly, verify-recovered-nightly-next, publish-nightly, generate-nightly-deltas, republish-nightly-deltas, sign-release-notes, publish-release-notes] + needs: [decide, build-nightly-ghostty-cli-helper, build-nightly-app, resolve-nightly-cmux-tui-client, prepare-nightly-variant, build-sign-notarize-nightly, verify-signed-nightly, verify-recovered-nightly-next, publish-nightly, generate-nightly-deltas, republish-nightly-deltas, sign-release-notes, check-release-notes, publish-release-notes] if: always() && needs.decide.outputs.should_publish == 'true' && needs.decide.outputs.notary_test != 'true' && (contains(needs.*.result, 'failure') || contains(needs.*.result, 'cancelled') || needs.publish-nightly.outputs.tag_status == 'stale' || needs.publish-nightly.outputs.refusal_reason != '' || (needs.decide.outputs.track == 'nightly-next' && needs.publish-nightly.result == 'success' && needs.publish-nightly.outputs.already_published != 'true' && needs.publish-nightly.outputs.refused != 'true' && needs.publish-nightly.outputs.source != 'recovered' && (needs.sign-release-notes.result != 'success' || needs.publish-release-notes.result != 'success'))) runs-on: ${{ github.repository_owner != 'manaflow-ai' && 'ubuntu-24.04' || vars.LINUX_RUNNER || 'blacksmith-4vcpu-ubuntu-2404' }} permissions: @@ -6441,7 +6490,7 @@ jobs: // nightly-next: notes jobs that were skipped after a publication // (a recovered one skips them on purpose). if (process.env.TRACK === 'nightly-next' && results['publish-nightly']?.result === 'success' && process.env.PUBLISH_SOURCE !== 'recovered') { - for (const job of ['sign-release-notes', 'publish-release-notes']) { + for (const job of ['sign-release-notes', 'check-release-notes', 'publish-release-notes']) { const result = results[job]?.result; if (result === 'skipped') failed.push(`${job} (skipped)`); } From eae368e11537a3023406de1b3253bae079ef3fc8 Mon Sep 17 00:00:00 2001 From: Leo Li Date: Mon, 19 Oct 2026 19:44:26 +0000 Subject: [PATCH 05/26] test(changelog): a brand-led title keeps its casing and passes the notes check; a multi-line highlight body is not an echo Co-Authored-By: Claude Opus 5.5 --- webviews/test/changelog-notes-check.test.ts | 24 +++++++++++++++++++++ webviews/test/changelog-readable.test.ts | 13 +++++++++++ 2 files changed, 37 insertions(+) diff --git a/webviews/test/changelog-notes-check.test.ts b/webviews/test/changelog-notes-check.test.ts index 83bb23716791..e89a2eb376b4 100644 --- a/webviews/test/changelog-notes-check.test.ts +++ b/webviews/test/changelog-notes-check.test.ts @@ -87,6 +87,30 @@ test("every one of the 50 published nightlies shows clean on the page and the ca } }); +test("a summary line that starts with a brand passes, as the pipeline published it", () => { + const { notes, previous } = at("3917159104301"); + const fixed = withEntries(notes, [{ ...notes.whatsNew!.entries[0]!, category: "fixed" }]); + const branded: ReleaseNotes = { + ...fixed, + summary: [...(fixed.summary ?? []), { group: "fixed", title: "MacOS 26 window shadows match the system" }], + }; + expect(checkNightlyNotes(branded, previous)).toEqual([]); +}); + +// The page shows a multi-line description as written (model.ts readableItem), so a highlight +// whose body opens with its title is not a title repeated as its description. +test("a highlight whose multi-line body opens with its title passes", () => { + const { notes, previous } = at("3917159104301"); + const fixed = withEntries(notes, [{ ...notes.whatsNew!.entries[0]!, category: "fixed" }]); + const highlighted: ReleaseNotes = { + ...fixed, + highlights: [ + { id: "rapid-switch", title: "Rapid switch", body: "Rapid switch keys move between tabs.\nThey follow focus." }, + ], + }; + expect(checkNightlyNotes(highlighted, previous)).toEqual([]); +}); + // The nightly job runs the check as `bun scripts/cmux-next/check-release-notes.ts NOTES PREVIOUS…`. test("the command fails with one annotation per defect, and passes clean notes", async () => { const { mkdtempSync, writeFileSync } = await import("node:fs"); diff --git a/webviews/test/changelog-readable.test.ts b/webviews/test/changelog-readable.test.ts index cb4f53fa329d..f946291e3100 100644 --- a/webviews/test/changelog-readable.test.ts +++ b/webviews/test/changelog-readable.test.ts @@ -117,6 +117,17 @@ test("base reds, branch names and compile fixes are internal work", () => { ); }); +// A subject that starts with a brand keeps its casing ("macOS", not "MacOS"), and notes that +// already carry "MacOS" (published before this rule) are not internal work. +test("a title that starts with a brand keeps the brand's casing", () => { + expect(readableChange("fix: macOS 26 window shadows match the system")).toMatchObject({ + title: "macOS 26 window shadows match the system", + internal: false, + }); + expect(readableChange("MacOS 26 window shadows match the system").internal).toBe(false); + expect(readableChange("iPhone pairing shows the Mac's name").title).toBe("iPhone pairing shows the Mac's name"); +}); + // The page reads notes published before the pipeline's rules (scripts/cmux-next/release-notes.py // summary_entry and short_title) the same way the pipeline reads new ones: every subject of the // medium span and of the 50 nightlies the gallery shows. @@ -125,6 +136,8 @@ test("the page and the pipeline read every subject of the span alike", () => { ...new Set([ ...(span as ReleaseNotes[]).flatMap((n) => n.changes), ...(nightlies as ReleaseNotes[]).flatMap((n) => changeItems(n).map((c) => c.title)), + "fix: macOS 26 window shadows match the system", + "iPhone pairing shows the Mac's name", ]), ]; const script = ` From 9c0e49061614b0468f86ec86fc8f4e29b5eb6cc8 Mon Sep 17 00:00:00 2001 From: Leo Li Date: Mon, 19 Oct 2026 19:49:26 +0000 Subject: [PATCH 06/26] cmux NEXT: brand-led titles keep their casing and pass the notes check; the check reads multi-line descriptions as the page does; the job skips a build commit without the check and fails on a bad index Co-Authored-By: Claude Opus 5.5 --- .github/workflows/nightly.yml | 18 ++++++++++++++---- scripts/cmux-next/release-notes.py | 17 +++++++++++++---- webviews/src/pages/changelog/notesCheck.ts | 7 +++++-- webviews/src/pages/changelog/readableChange.ts | 9 ++++++--- 4 files changed, 38 insertions(+), 13 deletions(-) diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml index 1a4f5d5214e7..1687aa39c215 100644 --- a/.github/workflows/nightly.yml +++ b/.github/workflows/nightly.yml @@ -6322,8 +6322,11 @@ jobs: # show them. A title cut with "…", a bead id, a title shown twice or as its own description, or # internal work in New, Improved or Fixed fails it, and publish-release-notes waits for it # (scripts/cmux-next/check-release-notes.ts). Only this build's defects count, so a defect an - # older nightly already published never blocks the notes after it. No secrets: it reads the - # artifact and the public feed (an unverified older file can only fail the check, never pass it). + # older nightly already published never blocks the notes after it. Withheld notes are not lost: + # the next build's span starts at the newest published notes, so it carries the same commits and + # fails the same way until the rule or the line is fixed (report-nightly-failure opens the issue). + # No secrets: it reads the artifact and the public feed (an unverified older file can only fail + # the check, never pass it). check-release-notes: needs: [decide, build-nightly-app, sign-release-notes, resolve-nightly-cmux-tui-client] if: "!cancelled() && needs.decide.outputs.track == 'nightly-next' && needs.sign-release-notes.result == 'success'" @@ -6352,18 +6355,25 @@ jobs: - name: Check this build's notes as the page and the update card show them run: | set -euo pipefail + # A build commit from before the check landed has no script to run. + if [ ! -f scripts/cmux-next/check-release-notes.ts ]; then + echo "::warning title=Release notes::$NIGHTLY_BUILD: the build commit has no notes check; not checked" + exit 0 + fi # The nine nightlies listed before this one, newest first: the artifact's copy when the - # backfill rewrote it, else the published file. + # backfill rewrote it, else the published file. A bad index fails here, not silently. + builds="$(python3 -c 'import json, sys; builds = [b["build"] for b in json.load(open(sys.argv[1]))["builds"] if b["build"] != sys.argv[2]]; print("\n".join(builds[:9]))' notes/index.json "$NIGHTLY_BUILD")" mkdir -p previous previous=() while IFS= read -r build; do + [ -n "$build" ] || continue file="notes/$build.json" if [ ! -f "$file" ]; then file="previous/$build.json" curl -fsSL --retry 3 -A "cmux-release-notes/1" -o "$file" "$NIGHTLY_NEXT_FEED_BASE/notes/$build.json" || continue fi previous+=("$file") - done < <(python3 -c 'import json, sys; builds = [b["build"] for b in json.load(open(sys.argv[1]))["builds"] if b["build"] != sys.argv[2]]; print("\n".join(builds[:9]))' notes/index.json "$NIGHTLY_BUILD") + done <<< "$builds" bun scripts/cmux-next/check-release-notes.ts "notes/$NIGHTLY_BUILD.json" "${previous[@]}" publish-release-notes: diff --git a/scripts/cmux-next/release-notes.py b/scripts/cmux-next/release-notes.py index 5fc37bff64f9..dbb6e7610bc4 100755 --- a/scripts/cmux-next/release-notes.py +++ b/scripts/cmux-next/release-notes.py @@ -64,8 +64,8 @@ r"machine code|scene captures?|policy log|host log|force unwrap|store intent|property model|false positive|inventory|" r"boundary|on the wire|debug reports?|dom events?|keybind actions?|main actor|shims?|" r"consumers?|metrics|review fixes|base reds?|feat-cmux-next|compile fix(?:es)?)\b", re.I) -# Product names whose casing is not code. -BRANDS = re.compile(r"\b(?:macOS|iOS|iPadOS|iCloud|iPhone|iPad|GitHub|YouTube|SwiftUI|WebKit|JavaScript|TypeScript|ChatGPT|OpenAI)\b") +# Product names whose casing is not code ("MacOS": a title capitalized before LEADING_BRAND). +BRANDS = re.compile(r"\b(?:[Mm]acOS|[Ii]OS|[Ii]PadOS|[Ii]Cloud|[Ii]Phone|[Ii]Pad|GitHub|YouTube|SwiftUI|WebKit|JavaScript|TypeScript|ChatGPT|OpenAI)\b") # Code-looking subjects (dotted names, snake_case, versioned ids, bead ids, backticks) are internal. CODE_LIKE = re.compile(r"`|\b[A-Za-z_]\w*\.[A-Za-z_]\w*\b|\w_\w|\w-v\d\b|\[cx-|\bcx-[a-z0-9]{3,}|\b[a-z]+[A-Z]\w*|\b[A-Z][a-z]+[A-Z]\w*|\b[A-Z]{2,}(?:-[A-Z]+)+\b|\{\w+\}") CONVENTIONAL = re.compile(r"^(?P[A-Za-z-]+)(?:\((?P[^)]*)\))?!?:\s*(?P.+)$") @@ -79,6 +79,15 @@ # subject, and a bead reference cut off at the end. REFS = re.compile(r"\s*\((?:[^()]*\bcx-[\w.]+[^()]*|[\w-]*#\d+|red|review)\)|\s*\((?:[^()]*\b)?cx-[\w.]*$", re.I) +# A brand that starts lowercase keeps its casing at the start of a title: "macOS 26 …". +LEADING_BRAND = re.compile(r"^(?:macOS|iOS|iPadOS|iCloud|iPhone|iPad)\b") + + +def capitalized(text): + """The text with a capital first letter, unless it starts with a lowercase brand.""" + return text if LEADING_BRAND.match(text) else text[:1].upper() + text[1:] + + def summary_entry(subject): """(group, title) for a user-facing commit subject, else None.""" text = " ".join(subject.split()) @@ -111,7 +120,7 @@ def summary_entry(subject): elif group == "changed" and re.match(r"^(fix|fixes|repair|stop|keep)\b", text, re.I): group = "fixed" # Whole: the page wraps a long line, and short_title gives the digest a title that fits. - return group, text[:1].upper() + text[1:] + return group, capitalized(text) CLAUSE = re.compile(r",|;| —| - | \(| so | because | while ") @@ -139,7 +148,7 @@ def title_tail(full, title): tail = full[len(title):].lstrip(" ,;:—-").strip() if tail.startswith("(") and tail.endswith(")"): tail = tail[1:-1] - return tail[:1].upper() + tail[1:] + return capitalized(tail) def summarize_changes(subjects, limit=SUMMARY_LIMIT): diff --git a/webviews/src/pages/changelog/notesCheck.ts b/webviews/src/pages/changelog/notesCheck.ts index 4e1b9c12bac6..e71b1c52703d 100644 --- a/webviews/src/pages/changelog/notesCheck.ts +++ b/webviews/src/pages/changelog/notesCheck.ts @@ -52,8 +52,11 @@ function rowDefects(where: NotesDefect["where"], rows: Row[], shown: boolean): N if (CUT.test(title)) defects.push({ kind: "truncated", where, text: title }); if (BEAD.test(title) || BEAD.test(summary)) defects.push({ kind: "bead", where, text: title }); if (row.machine && readableChange(title).internal) defects.push({ kind: "internal", where, text: title }); - // The page and the card show the summary beside the title; the notes may carry both alike. - const echoes = summary && (key(summary) === key(title) || key(summary).startsWith(`${key(title)} `)); + // The page and the card show the summary beside the title; the notes may carry both alike. A + // multi-line description shows as written (model.ts readableItem), so only a one-line summary + // that opens with the title echoes it. + const opens = !summary.includes("\n") && key(summary).startsWith(`${key(title)} `); + const echoes = summary && (key(summary) === key(title) || opens); if (titles.has(key(title)) || (shown && echoes)) defects.push({ kind: "duplicate", where, text: title }); titles.add(key(title)); } diff --git a/webviews/src/pages/changelog/readableChange.ts b/webviews/src/pages/changelog/readableChange.ts index 977fcffcb76e..9e3786d1de9c 100644 --- a/webviews/src/pages/changelog/readableChange.ts +++ b/webviews/src/pages/changelog/readableChange.ts @@ -64,9 +64,9 @@ const INTERNAL_WORDS = new RegExp( String.raw`consumers?|metrics|review fixes|base reds?|feat-cmux-next|compile fix(?:es)?)\b`, "i", ); -/** Product names whose casing is not code. */ +/** Product names whose casing is not code ("MacOS": a title capitalized before LEADING_BRAND). */ const BRANDS = - /\b(?:macOS|iOS|iPadOS|iCloud|iPhone|iPad|GitHub|YouTube|SwiftUI|WebKit|JavaScript|TypeScript|ChatGPT|OpenAI)\b/g; + /\b(?:[Mm]acOS|[Ii]OS|[Ii]PadOS|[Ii]Cloud|[Ii]Phone|[Ii]Pad|GitHub|YouTube|SwiftUI|WebKit|JavaScript|TypeScript|ChatGPT|OpenAI)\b/g; /** Code-looking text: backticks, dotted names, snake_case, versioned ids, bead ids, camelCase, {placeholders}. */ const CODE_LIKE = @@ -95,8 +95,11 @@ export interface ReadableChange { group: ChangeGroup; } +/** A brand that starts lowercase keeps its casing at the start of a title: "macOS 26 …". */ +const LEADING_BRAND = /^(?:macOS|iOS|iPadOS|iCloud|iPhone|iPad)\b/; + function capitalized(text: string): string { - return text.charAt(0).toUpperCase() + text.slice(1); + return LEADING_BRAND.test(text) ? text : text.charAt(0).toUpperCase() + text.slice(1); } function strip(text: string): string { From a206ed1076eedf4de5d7690a93bc5c090340adfb Mon Sep 17 00:00:00 2001 From: Leo Li Date: Mon, 19 Oct 2026 19:59:38 +0000 Subject: [PATCH 07/26] ci(nightly-next): the notes check warns when the feed did not serve an older nightly, and names the span it read Co-Authored-By: Claude Opus 5.5 --- .github/workflows/nightly.yml | 10 +++++++++- scripts/cmux-next/check-release-notes.ts | 2 +- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml index 1687aa39c215..e1f093fc6b87 100644 --- a/.github/workflows/nightly.yml +++ b/.github/workflows/nightly.yml @@ -6365,15 +6365,23 @@ jobs: builds="$(python3 -c 'import json, sys; builds = [b["build"] for b in json.load(open(sys.argv[1]))["builds"] if b["build"] != sys.argv[2]]; print("\n".join(builds[:9]))' notes/index.json "$NIGHTLY_BUILD")" mkdir -p previous previous=() + missing=() while IFS= read -r build; do [ -n "$build" ] || continue file="notes/$build.json" if [ ! -f "$file" ]; then file="previous/$build.json" - curl -fsSL --retry 3 -A "cmux-release-notes/1" -o "$file" "$NIGHTLY_NEXT_FEED_BASE/notes/$build.json" || continue + if ! curl -fsSL --retry 3 -A "cmux-release-notes/1" -o "$file" "$NIGHTLY_NEXT_FEED_BASE/notes/$build.json"; then + missing+=("$build") + continue + fi fi previous+=("$file") done <<< "$builds" + # A feed outage narrows the wider page; say so instead of passing it as 10 nightlies. + if [ "${#missing[@]}" -gt 0 ]; then + echo "::warning title=Release notes::$NIGHTLY_BUILD: the wider page lacks ${#missing[@]} nightlies the feed did not serve: ${missing[*]}" + fi bun scripts/cmux-next/check-release-notes.ts "notes/$NIGHTLY_BUILD.json" "${previous[@]}" publish-release-notes: diff --git a/scripts/cmux-next/check-release-notes.ts b/scripts/cmux-next/check-release-notes.ts index c690d42a82dc..ac4361d3572f 100644 --- a/scripts/cmux-next/check-release-notes.ts +++ b/scripts/cmux-next/check-release-notes.ts @@ -19,4 +19,4 @@ const previous = previousPaths.slice(0, RANGE - 1).map(read); const defects = checkNightlyNotes(notes, previous); for (const defect of defects) console.log(annotation(notes.build, defect)); if (defects.length > 0) process.exit(1); -console.log(`${notes.build}: notes, page (1 and ${RANGE} nightlies) and card read clean`); +console.log(`${notes.build}: notes, page (1 and ${previous.length + 1} nightlies) and card read clean`); From 29c94bd58bf1ed389b9a3dd80be02bd6588e0829 Mon Sep 17 00:00:00 2001 From: Leo Li Date: Mon, 19 Oct 2026 21:54:33 +0000 Subject: [PATCH 08/26] test(changelog): tool names, PR numbers and squash repairs in summary lines are internal work (failing) Co-Authored-By: Claude Opus 5.5 --- webviews/test/changelog-notes-check.test.ts | 33 +++++++++++++-------- webviews/test/changelog-readable.test.ts | 18 +++++++++++ 2 files changed, 38 insertions(+), 13 deletions(-) diff --git a/webviews/test/changelog-notes-check.test.ts b/webviews/test/changelog-notes-check.test.ts index e89a2eb376b4..a8e994f8b2c7 100644 --- a/webviews/test/changelog-notes-check.test.ts +++ b/webviews/test/changelog-notes-check.test.ts @@ -22,27 +22,34 @@ function withEntries(notes: ReleaseNotes, entries: WhatsNewEntry[]): ReleaseNote return { ...notes, whatsNew: { ...notes.whatsNew!, entries } }; } -test("3917159104301 as published fails on its cut digest title; the page and card show it whole", () => { +test("3917159104301 as published fails on its cut digest title and its tool-name line", () => { const { notes, previous } = at("3917159104301"); - const defects = checkNightlyNotes(notes, previous); - expect(defects).toEqual([ - { - kind: "truncated", - where: "notes", - text: "Export-backdrop-art reads each entry's subject box and…", - }, - ]); + const defects = checkNightlyNotes(notes, previous).map((d) => `${d.where} ${d.kind} ${d.text}`); + expect(defects).toContain("notes truncated Export-backdrop-art reads each entry's subject box and…"); + expect(defects).toContain("notes internal Export-backdrop-art reads each entry's subject box and exports it"); + expect(defects.every((d) => d.startsWith("notes "))).toBe(true); }); test("notes as the current pipeline writes them pass, alone and with the nine nightlies before them", () => { const { notes, previous } = at("3917159104301"); - const fixed = withEntries(notes, [ - { ...notes.whatsNew!.entries[0]!, category: "fixed" }, - digestEntry("summary-1", "Export-backdrop-art reads each entry's subject box and exports it"), - ]); + const fixed = { + ...withEntries(notes, [{ ...notes.whatsNew!.entries[0]!, category: "fixed" }]), + summary: (notes.summary ?? []).filter((line) => !line.title.startsWith("Export-backdrop-art")), + }; expect(checkNightlyNotes(fixed, previous)).toEqual([]); }); +test("published summary lines naming PR numbers or a squash fail as internal work", () => { + const tour = at("3917061587901"); + expect(checkNightlyNotes(tour.notes, tour.previous).map((d) => `${d.where} ${d.kind} ${d.text}`)).toContain( + "notes internal Tour uploads stop naming the PR as #N", + ); + const squash = at("3914841887501"); + const defects = checkNightlyNotes(squash.notes, squash.previous).map((d) => `${d.where} ${d.kind} ${d.text}`); + expect(defects).toContain("notes internal Restore the URL chip hover card styles lost in the Chief Dock squash"); + expect(defects).toContain("notes internal Restore #21369 and #21384, undone by the Chief Dock squash"); +}); + test("a leaked bead id, a cut title and internal work in the build's own lines fail", () => { const { notes, previous } = at("3917159104301"); const bad: ReleaseNotes = { diff --git a/webviews/test/changelog-readable.test.ts b/webviews/test/changelog-readable.test.ts index f946291e3100..a304853394b8 100644 --- a/webviews/test/changelog-readable.test.ts +++ b/webviews/test/changelog-readable.test.ts @@ -40,6 +40,24 @@ test("All Changes lists each human change once and folds internal work into a co expect(view.changes.find((c) => c.pr === 21592)?.title).toBe("Restore workspace title motion tunable"); }); +// The 49-nightly gallery range (2026-10-19) showed these published commit subjects under Improved +// and Fixed: a tool name, PR numbers and history repair are work no user sees. +test("tool-name, PR-number and history-repair commits are internal work", () => { + for (const subject of [ + "cmux-next: export-backdrop-art reads each entry's subject box and exports it", + "cmux-next media: tour uploads stop naming the PR as #N", + "fix(cmux-next): restore the URL chip hover card styles lost in the Chief Dock squash", + "fix(cmux-next): restore #21369 and #21384, undone by the Chief Dock squash", + ]) + expect(readableChange(subject).internal).toBe(true); + for (const subject of [ + "fix(cmux-next): keep the sidebar up-to-date after a rename", + "feat(cmux-next): drag-and-drop a file into a terminal", + "feat: side-by-side diffs in the review pane", + ]) + expect(readableChange(subject).internal).toBe(false); +}); + test("readable change titles", () => { expect(readableChange("cmux NEXT perf-split: snapshot sources name a new pane's first runs (cx-8w027.14)")).toEqual({ title: "Snapshot sources name a new pane's first runs", From 135feedb9546123028ddf5fbceaecdfe29c7f1be Mon Sep 17 00:00:00 2001 From: Leo Li Date: Mon, 19 Oct 2026 21:56:51 +0000 Subject: [PATCH 09/26] fix(changelog): a tool name, a PR number or a squash repair marks a line internal The 49-nightly gallery range showed export-backdrop-art, "#N", "#21369 and #21384" and two Chief Dock squash repairs under Improved and Fixed. readableChange and release-notes.py now read a three-part hyphenated tool name (not up-to-date or drag-and-drop), a bare PR number and squash as internal, so the page folds them, the pipeline leaves them out of summary lines, and the pre-publish check fails a build whose notes still carry one. Co-Authored-By: Claude Opus 5.5 --- scripts/cmux-next/release-notes.py | 7 +++--- .../src/pages/changelog/readableChange.ts | 7 +++--- webviews/test/changelog-notes-check.test.ts | 22 ++++++++++++------- webviews/test/update-ready-popover.test.tsx | 12 ++++------ 4 files changed, 26 insertions(+), 22 deletions(-) diff --git a/scripts/cmux-next/release-notes.py b/scripts/cmux-next/release-notes.py index dbb6e7610bc4..9bd3f89a4db2 100755 --- a/scripts/cmux-next/release-notes.py +++ b/scripts/cmux-next/release-notes.py @@ -63,11 +63,12 @@ r"frame budget|osc \d+|terminal host|seed|record\w*|nightly|headless|ffi|rust|regenerate|decode|renderer|texture|" r"machine code|scene captures?|policy log|host log|force unwrap|store intent|property model|false positive|inventory|" r"boundary|on the wire|debug reports?|dom events?|keybind actions?|main actor|shims?|" - r"consumers?|metrics|review fixes|base reds?|feat-cmux-next|compile fix(?:es)?)\b", re.I) + r"consumers?|metrics|review fixes|base reds?|feat-cmux-next|compile fix(?:es)?|squash(?:ed|es)?)\b", re.I) # Product names whose casing is not code ("MacOS": a title capitalized before LEADING_BRAND). BRANDS = re.compile(r"\b(?:[Mm]acOS|[Ii]OS|[Ii]PadOS|[Ii]Cloud|[Ii]Phone|[Ii]Pad|GitHub|YouTube|SwiftUI|WebKit|JavaScript|TypeScript|ChatGPT|OpenAI)\b") -# Code-looking subjects (dotted names, snake_case, versioned ids, bead ids, backticks) are internal. -CODE_LIKE = re.compile(r"`|\b[A-Za-z_]\w*\.[A-Za-z_]\w*\b|\w_\w|\w-v\d\b|\[cx-|\bcx-[a-z0-9]{3,}|\b[a-z]+[A-Z]\w*|\b[A-Z][a-z]+[A-Z]\w*|\b[A-Z]{2,}(?:-[A-Z]+)+\b|\{\w+\}") +# Code-looking subjects (dotted names, snake_case, versioned ids, bead ids, backticks, a PR number, +# a tool name of three or more hyphenated parts) are internal. +CODE_LIKE = re.compile(r"`|\b[A-Za-z_]\w*\.[A-Za-z_]\w*\b|\w_\w|\w-v\d\b|\[cx-|\bcx-[a-z0-9]{3,}|\b[a-z]+[A-Z]\w*|\b[A-Z][a-z]+[A-Z]\w*|\b[A-Z]{2,}(?:-[A-Z]+)+\b|\{\w+\}|(?:^|\s)#(?:\d+|N)\b|\b(?![\w-]*-(?:to|by|of|and|in|the|a|an|on|for|or|at|with)(?:-|\b))[A-Za-z][a-z0-9]*(?:-[a-z0-9]+){2,}\b") CONVENTIONAL = re.compile(r"^(?P[A-Za-z-]+)(?:\((?P[^)]*)\))?!?:\s*(?P.+)$") AREA_PREFIX = re.compile(r"^(cmux-next(?: \w+){0,2}|cmuxnext|cmux next|acpmux|apps?|browser|gallery|release notes?|cx-[\w.]+|feed [\d.]+|cmux-tui)\s*:\s*", re.I) # "area words: rest" after the conventional type: "cmux NEXT perf-split: review: …", "cmux-next strip: …". diff --git a/webviews/src/pages/changelog/readableChange.ts b/webviews/src/pages/changelog/readableChange.ts index 9e3786d1de9c..d3a4209d1488 100644 --- a/webviews/src/pages/changelog/readableChange.ts +++ b/webviews/src/pages/changelog/readableChange.ts @@ -61,16 +61,17 @@ const INTERNAL_WORDS = new RegExp( String.raw`frame budget|osc \d+|terminal host|seed|record\w*|nightly|headless|ffi|rust|regenerate|decode|renderer|texture|` + String.raw`machine code|scene captures?|policy log|host log|force unwrap|store intent|property model|false positive|inventory|` + String.raw`boundary|on the wire|debug reports?|dom events?|keybind actions?|main actor|shims?|` + - String.raw`consumers?|metrics|review fixes|base reds?|feat-cmux-next|compile fix(?:es)?)\b`, + String.raw`consumers?|metrics|review fixes|base reds?|feat-cmux-next|compile fix(?:es)?|squash(?:ed|es)?)\b`, "i", ); /** Product names whose casing is not code ("MacOS": a title capitalized before LEADING_BRAND). */ const BRANDS = /\b(?:[Mm]acOS|[Ii]OS|[Ii]PadOS|[Ii]Cloud|[Ii]Phone|[Ii]Pad|GitHub|YouTube|SwiftUI|WebKit|JavaScript|TypeScript|ChatGPT|OpenAI)\b/g; /** Code-looking text: backticks, dotted names, snake_case, versioned ids, bead ids, camelCase, - {placeholders}. */ + {placeholders}, a PR number ("#21369", "#N") and a tool name of three or more hyphenated parts + ("export-backdrop-art"; "up-to-date" and "drag-and-drop" join with a short word and stay). */ const CODE_LIKE = - /`|\b[A-Za-z_]\w*\.[A-Za-z_]\w*\b|\w_\w|\w-v\d\b|\[cx-|\bcx-[a-z0-9]{3,}|\b[a-z]+[A-Z]\w*|\b[A-Z][a-z]+[A-Z]\w*|\b[A-Z]{2,}(?:-[A-Z]+)+\b|\{\w+\}/; + /`|\b[A-Za-z_]\w*\.[A-Za-z_]\w*\b|\w_\w|\w-v\d\b|\[cx-|\bcx-[a-z0-9]{3,}|\b[a-z]+[A-Z]\w*|\b[A-Z][a-z]+[A-Z]\w*|\b[A-Z]{2,}(?:-[A-Z]+)+\b|\{\w+\}|(?:^|\s)#(?:\d+|N)\b|\b(?![\w-]*-(?:to|by|of|and|in|the|a|an|on|for|or|at|with)(?:-|\b))[A-Za-z][a-z0-9]*(?:-[a-z0-9]+){2,}\b/; const CONVENTIONAL = /^(?[A-Za-z-]+)(?:\((?[^)]*)\))?!?:\s*(?.+)$/; /** "area words: rest" after the conventional type: "cmux NEXT perf-split: review: …", "cmux-next strip: …". */ const LABEL = /^(?[A-Za-z][\w-]*(?: [A-Za-z][\w-]*){0,2})(?:\((?[^)]*)\))?!?:\s+(?\S.*)$/; diff --git a/webviews/test/changelog-notes-check.test.ts b/webviews/test/changelog-notes-check.test.ts index a8e994f8b2c7..f9db73c6c363 100644 --- a/webviews/test/changelog-notes-check.test.ts +++ b/webviews/test/changelog-notes-check.test.ts @@ -22,6 +22,15 @@ function withEntries(notes: ReleaseNotes, entries: WhatsNewEntry[]): ReleaseNote return { ...notes, whatsNew: { ...notes.whatsNew!, entries } }; } +/** 3917159104301 as the current pipeline writes it: its first entry under Fixed, and no + tool-name summary line (export-backdrop-art is internal work). */ +function clean(notes: ReleaseNotes): ReleaseNotes { + return { + ...withEntries(notes, [{ ...notes.whatsNew!.entries[0]!, category: "fixed" }]), + summary: (notes.summary ?? []).filter((line) => !line.title.startsWith("Export-backdrop-art")), + }; +} + test("3917159104301 as published fails on its cut digest title and its tool-name line", () => { const { notes, previous } = at("3917159104301"); const defects = checkNightlyNotes(notes, previous).map((d) => `${d.where} ${d.kind} ${d.text}`); @@ -32,10 +41,7 @@ test("3917159104301 as published fails on its cut digest title and its tool-name test("notes as the current pipeline writes them pass, alone and with the nine nightlies before them", () => { const { notes, previous } = at("3917159104301"); - const fixed = { - ...withEntries(notes, [{ ...notes.whatsNew!.entries[0]!, category: "fixed" }]), - summary: (notes.summary ?? []).filter((line) => !line.title.startsWith("Export-backdrop-art")), - }; + const fixed = clean(notes); expect(checkNightlyNotes(fixed, previous)).toEqual([]); }); @@ -80,7 +86,7 @@ test("a reviewed entry the page would show twice, or with its title as its descr test("a defect only an older nightly has is not this build's to fix", () => { const { notes, previous } = at("3917159104301"); - const fixed = withEntries(notes, [{ ...notes.whatsNew!.entries[0]!, category: "fixed" }]); + const fixed = clean(notes); const older = previous.map((n, i) => i === 0 ? { ...n, highlights: [{ id: "old", title: "An old highlight cut short…", body: "" }] } : n, ); @@ -96,7 +102,7 @@ test("every one of the 50 published nightlies shows clean on the page and the ca test("a summary line that starts with a brand passes, as the pipeline published it", () => { const { notes, previous } = at("3917159104301"); - const fixed = withEntries(notes, [{ ...notes.whatsNew!.entries[0]!, category: "fixed" }]); + const fixed = clean(notes); const branded: ReleaseNotes = { ...fixed, summary: [...(fixed.summary ?? []), { group: "fixed", title: "MacOS 26 window shadows match the system" }], @@ -108,7 +114,7 @@ test("a summary line that starts with a brand passes, as the pipeline published // whose body opens with its title is not a title repeated as its description. test("a highlight whose multi-line body opens with its title passes", () => { const { notes, previous } = at("3917159104301"); - const fixed = withEntries(notes, [{ ...notes.whatsNew!.entries[0]!, category: "fixed" }]); + const fixed = clean(notes); const highlighted: ReleaseNotes = { ...fixed, highlights: [ @@ -135,7 +141,7 @@ test("the command fails with one annotation per defect, and passes clean notes", expect(bad.stdout.toString()).toContain( "::error title=Release notes::3917159104301 notes: a cut title: Export-backdrop-art reads each entry's subject box and…", ); - const fixed = withEntries(notes, [{ ...notes.whatsNew!.entries[0]!, category: "fixed" }]); + const fixed = clean(notes); writeFileSync(files[0]!, JSON.stringify(fixed)); const good = Bun.spawnSync([process.execPath, script, ...files]); expect([good.exitCode, good.stdout.toString()]).toEqual([ diff --git a/webviews/test/update-ready-popover.test.tsx b/webviews/test/update-ready-popover.test.tsx index ca00f27bacd3..ca96755e2d01 100644 --- a/webviews/test/update-ready-popover.test.tsx +++ b/webviews/test/update-ready-popover.test.tsx @@ -153,10 +153,8 @@ test("the popup and the card read notes published before the readable rules as t ), ); const items = [...host.querySelectorAll(".wn-pop-list li")].map((li) => li.textContent); - expect(items).toEqual([ - "1Export-backdrop-art reads each entry's subject box and exports it", - "2Keep the Mac awake while agents work", - ]); + // The perf-fanout line and the export-backdrop-art tool line are internal work. + expect(items).toEqual(["1Keep the Mac awake while agents work"]); act(() => root?.unmount()); root = createRoot(host); await act(async () => @@ -164,8 +162,6 @@ test("the popup and the card read notes published before the readable rules as t undefined }} />, ), ); - expect(host.querySelector(".wn-card-headline")?.textContent).toBe( - "Export-backdrop-art reads each entry's subject box and exports it", - ); - expect(host.querySelector(".wn-card-line")?.textContent).toBe("+1 more"); + expect(host.querySelector(".wn-card-headline")?.textContent).toBe("Keep the Mac awake while agents work"); + expect(host.querySelector(".wn-card-line")).toBeNull(); }); From 0fbda72415d236b8a767285baed7bdbfbcda9318 Mon Sep 17 00:00:00 2001 From: Leo Li Date: Mon, 19 Oct 2026 22:03:12 +0000 Subject: [PATCH 10/26] test(changelog): review cases for the notes rules: user-facing hyphen names, #1, squash commits, a menu ellipsis, repeated digest titles (failing) Co-Authored-By: Claude Opus 5.5 --- tests/test_cmux_next_release_notes.py | 17 ++++++++++++++ webviews/test/changelog-notes-check.test.ts | 10 ++++++++ webviews/test/changelog-readable.test.ts | 26 +++++++++++++++++++++ 3 files changed, 53 insertions(+) diff --git a/tests/test_cmux_next_release_notes.py b/tests/test_cmux_next_release_notes.py index 4582ec779aa1..933806ce8981 100644 --- a/tests/test_cmux_next_release_notes.py +++ b/tests/test_cmux_next_release_notes.py @@ -16,6 +16,23 @@ def git(cwd, *args): class ReleaseNotesTests(unittest.TestCase): + def test_digest_titles_are_unique_when_long_lines_share_a_first_clause(self): + # Review of #22099: short_title cuts both lines to "Sidebar rows keep their order", + # and the pre-publish check rejects a digest that shows one title twice. + import argparse, importlib.util + script = os.path.join(os.path.dirname(os.path.abspath(__file__)), "..", "scripts", "cmux-next", "release-notes.py") + spec = importlib.util.spec_from_file_location("release_notes_digest", script) + notes = importlib.util.module_from_spec(spec) + spec.loader.exec_module(notes) + lines = [ + {"group": "fixed", "title": "Sidebar rows keep their order, even when a workspace is renamed while another one is dragged"}, + {"group": "fixed", "title": "Sidebar rows keep their order, after a relaunch restores every window and each of its workspaces"}, + ] + args = argparse.Namespace(short="1.0.0-nightly.1", date="2026-10-19") + digest = notes.summary_whats_new_digest(args, lines) + titles = [entry["title"]["en"].lower() for entry in digest["entries"]] + self.assertEqual(len(titles), len(set(titles)), titles) + def setUp(self): self.repo = tempfile.mkdtemp() git(self.repo, "init", "-q") diff --git a/webviews/test/changelog-notes-check.test.ts b/webviews/test/changelog-notes-check.test.ts index f9db73c6c363..af9b6b72d08a 100644 --- a/webviews/test/changelog-notes-check.test.ts +++ b/webviews/test/changelog-notes-check.test.ts @@ -74,6 +74,16 @@ test("a leaked bead id, a cut title and internal work in the build's own lines f expect(kinds).toContain("notes truncated Tabs reopen where they were..."); }); +// The generator keeps a menu command's ellipsis ("Rename Workspace…"); only a cut sentence fails. +test("a title ending in a menu command's ellipsis passes", () => { + const { notes, previous } = at("3917159104301"); + const menu: ReleaseNotes = { + ...clean(notes), + summary: [...(clean(notes).summary ?? []), { group: "new", title: "Rename Workspace…" }], + }; + expect(checkNightlyNotes(menu, previous)).toEqual([]); +}); + test("a reviewed entry the page would show twice, or with its title as its description, fails", () => { const { notes, previous } = at("3917159104301"); const twice = withEntries(notes, [ diff --git a/webviews/test/changelog-readable.test.ts b/webviews/test/changelog-readable.test.ts index a304853394b8..218a3e47701e 100644 --- a/webviews/test/changelog-readable.test.ts +++ b/webviews/test/changelog-readable.test.ts @@ -58,6 +58,29 @@ test("tool-name, PR-number and history-repair commits are internal work", () => expect(readableChange(subject).internal).toBe(false); }); +// Review of #22099 (2026-10-19): user-facing titles the tool-name, PR-number and squash rules +// must leave alone, a hyphenated name with a non-ASCII letter included. +const USER_FACING = [ + "feat(cmux-next): two-finger-swipe goes back in the browser", + "feat(cmux-next): cmd-shift-t reopens the last closed tab", + "feat(cmux-next): do-not-disturb holds notifications while you present", + "fix(cmux-next): the pop-up-menu closes on Escape", + "feat(cmux-next): a follow-up-question chip under each answer", + "feat(cmux-next): per-tab-zoom remembers each tab's zoom", + "fix(cmux-next): utf-8-encoded file names open", + "fix(cmux-next): the #1 crash on wake is gone", + "feat(cmux-next): tabs #1 to #9 have shortcuts", + "feat(cmux-next): squash commits from the review pane", + "feat(cmux-next): end-to-end-encrypted sync of settings", + "fix(cmux-next): right-to-left-text lines wrap correctly", + "feat(cmux-next): side-by-side-diff view for changed files", + "feat: a naïve-mode-switch for the prompt", +]; + +test("hyphenated feature names, small numbers and squash commits stay user-facing", () => { + for (const subject of USER_FACING) expect([subject, readableChange(subject).internal]).toEqual([subject, false]); +}); + test("readable change titles", () => { expect(readableChange("cmux NEXT perf-split: snapshot sources name a new pane's first runs (cx-8w027.14)")).toEqual({ title: "Snapshot sources name a new pane's first runs", @@ -156,6 +179,9 @@ test("the page and the pipeline read every subject of the span alike", () => { ...(nightlies as ReleaseNotes[]).flatMap((n) => changeItems(n).map((c) => c.title)), "fix: macOS 26 window shadows match the system", "iPhone pairing shows the Mac's name", + ...USER_FACING, + "cmux-next: export-backdrop-art reads each entry's subject box and exports it", + "fix(cmux-next): restore #21369 and #21384, undone by the Chief Dock squash", ]), ]; const script = ` From 284322645c1bddace7432695bdeeaad9930e0a0a Mon Sep 17 00:00:00 2001 From: Leo Li Date: Mon, 19 Oct 2026 22:04:47 +0000 Subject: [PATCH 11/26] fix(changelog): narrow the internal rules, read them in ASCII on both sides, keep a menu ellipsis and dedupe digest titles Review of #22099: the hyphen rule hid two-finger-swipe, cmd-shift-t and per-tab-zoom; "#1" and "squash commits" read as internal; Python matched Unicode word characters the page did not; a menu command ellipsis failed as a cut title; and two long lines with one first clause gave the digest one title twice, which the pre-publish check rejects. A tool name now needs three parts none of which is a joining word, number word, modifier key or single character; a PR number is #N or three or more digits; a squash repair is "squash merge/commit" or a line ending in squash. Co-Authored-By: Claude Opus 5.5 --- scripts/cmux-next/release-notes.py | 21 +++++++++++----- webviews/src/pages/changelog/notesCheck.ts | 4 +++- .../src/pages/changelog/readableChange.ts | 24 +++++++++++++++---- 3 files changed, 37 insertions(+), 12 deletions(-) diff --git a/scripts/cmux-next/release-notes.py b/scripts/cmux-next/release-notes.py index 9bd3f89a4db2..b7d824d567fd 100755 --- a/scripts/cmux-next/release-notes.py +++ b/scripts/cmux-next/release-notes.py @@ -63,12 +63,17 @@ r"frame budget|osc \d+|terminal host|seed|record\w*|nightly|headless|ffi|rust|regenerate|decode|renderer|texture|" r"machine code|scene captures?|policy log|host log|force unwrap|store intent|property model|false positive|inventory|" r"boundary|on the wire|debug reports?|dom events?|keybind actions?|main actor|shims?|" - r"consumers?|metrics|review fixes|base reds?|feat-cmux-next|compile fix(?:es)?|squash(?:ed|es)?)\b", re.I) + r"consumers?|metrics|review fixes|base reds?|feat-cmux-next|compile fix(?:es)?)\b", re.I | re.A) # Product names whose casing is not code ("MacOS": a title capitalized before LEADING_BRAND). BRANDS = re.compile(r"\b(?:[Mm]acOS|[Ii]OS|[Ii]PadOS|[Ii]Cloud|[Ii]Phone|[Ii]Pad|GitHub|YouTube|SwiftUI|WebKit|JavaScript|TypeScript|ChatGPT|OpenAI)\b") -# Code-looking subjects (dotted names, snake_case, versioned ids, bead ids, backticks, a PR number, -# a tool name of three or more hyphenated parts) are internal. -CODE_LIKE = re.compile(r"`|\b[A-Za-z_]\w*\.[A-Za-z_]\w*\b|\w_\w|\w-v\d\b|\[cx-|\bcx-[a-z0-9]{3,}|\b[a-z]+[A-Z]\w*|\b[A-Z][a-z]+[A-Z]\w*|\b[A-Z]{2,}(?:-[A-Z]+)+\b|\{\w+\}|(?:^|\s)#(?:\d+|N)\b|\b(?![\w-]*-(?:to|by|of|and|in|the|a|an|on|for|or|at|with)(?:-|\b))[A-Za-z][a-z0-9]*(?:-[a-z0-9]+){2,}\b") +# Code-looking subjects (dotted names, snake_case, versioned ids, bead ids, backticks) are internal. +# ASCII classes, as JavaScript reads them in readableChange.ts. +CODE_LIKE = re.compile(r"`|\b[A-Za-z_]\w*\.[A-Za-z_]\w*\b|\w_\w|\w-v\d\b|\[cx-|\bcx-[a-z0-9]{3,}|\b[a-z]+[A-Z]\w*|\b[A-Z][a-z]+[A-Z]\w*|\b[A-Z]{2,}(?:-[A-Z]+)+\b|\{\w+\}", re.A) +# Work no user sees by its shape (readableChange.ts TOOL_NAME, PR_NUMBER, SQUASH_REPAIR): a tool name +# of three or more hyphenated parts, a pull request number, a repair after a squash. +TOOL_NAME = re.compile(r"(?[A-Za-z-]+)(?:\((?P[^)]*)\))?!?:\s*(?P.+)$") AREA_PREFIX = re.compile(r"^(cmux-next(?: \w+){0,2}|cmuxnext|cmux next|acpmux|apps?|browser|gallery|release notes?|cx-[\w.]+|feed [\d.]+|cmux-tui)\s*:\s*", re.I) # "area words: rest" after the conventional type: "cmux NEXT perf-split: review: …", "cmux-next strip: …". @@ -114,7 +119,8 @@ def summary_entry(subject): text = label["rest"] text = AREA_PREFIX.sub("", text) text = REFS.sub("", text).strip(" .") - if not text or INTERNAL_WORDS.search(text) or CODE_LIKE.search(BRANDS.sub("", text)): + if (not text or INTERNAL_WORDS.search(text) or CODE_LIKE.search(BRANDS.sub("", text)) + or TOOL_NAME.search(text) or PR_NUMBER.search(text) or SQUASH_REPAIR.search(text)): return None if group == "changed" and re.match(r"^(add|adds|new|introduce|support|show)\b", text, re.I): group = "new" @@ -256,11 +262,13 @@ def summary_whats_new_digest(args, lines): document = {"schemaVersion": 1, "version": args.short, "channel": "nightly", "date": args.date, "headline": {"en": "Fixes and improvements"}, "entries": []} categories = {"new": "new", "fixed": "fixed", "changed": "improved"} + titles = set() for index, line in enumerate(lines): # A line with no clause short enough stays out of the digest; the page shows it whole # from the summary lines. title = short_title(line.get("title", ""), validate.LIMITS["title"]) - if not title or line.get("group") not in categories: + # Two long lines can share a first clause; the digest shows each title once. + if not title or line.get("group") not in categories or title.lower() in titles: continue # The summary says what the title leaves out, or repeats a title that is the whole line. full = " ".join(line["title"].split()).rstrip(". ") @@ -272,6 +280,7 @@ def summary_whats_new_digest(args, lines): print(f"whats-new summary: dropped {entry['id']}:\n" + "\n".join(problems), file=sys.stderr) continue document["entries"].append(entry) + titles.add(title.lower()) if not document["entries"]: return None document["headline"] = {"en": document["entries"][0]["title"]["en"]} diff --git a/webviews/src/pages/changelog/notesCheck.ts b/webviews/src/pages/changelog/notesCheck.ts index e71b1c52703d..f510c702a5a3 100644 --- a/webviews/src/pages/changelog/notesCheck.ts +++ b/webviews/src/pages/changelog/notesCheck.ts @@ -26,7 +26,9 @@ export const RANGE = 10; /** Items the update card and popup get (UpdateHighlights.shownItems). */ const CARD_ITEMS = 3; const BEAD = /\bcx-[a-z0-9]{3,}(?:\.\d+)*\b/i; -const CUT = /(?:…|\.\.\.)$/u; +/** A sentence cut with "…" or "..."; a menu command keeps its ellipsis ("Rename Workspace…"), as + release-notes.py writes it. */ +const CUT = /(?[A-Za-z-]+)(?:\((?[^)]*)\))?!?:\s*(?.+)$/; /** "area words: rest" after the conventional type: "cmux NEXT perf-split: review: …", "cmux-next strip: …". */ const LABEL = /^(?[A-Za-z][\w-]*(?: [A-Za-z][\w-]*){0,2})(?:\((?[^)]*)\))?!?:\s+(?\S.*)$/; @@ -149,7 +155,15 @@ export function readableChange(subject: string): ReadableChange { text = label.rest!; } text = strip(text.replace(AREA_PREFIX, "")); - if (!text || INTERNAL_WORDS.test(text) || CODE_LIKE.test(text.replace(BRANDS, ""))) return internal(text); + if ( + !text || + INTERNAL_WORDS.test(text) || + CODE_LIKE.test(text.replace(BRANDS, "")) || + TOOL_NAME.test(text) || + PR_NUMBER.test(text) || + SQUASH_REPAIR.test(text) + ) + return internal(text); if (group === "changed" && /^(add|adds|new|introduce|support|show)\b/i.test(text)) group = "new"; else if (group === "changed" && /^(fix|fixes|repair|stop|keep)\b/i.test(text)) group = "fixed"; return { title: capitalized(text), internal: false, group }; From e219e634c984d94b8f453ebbd5e6224dcba9e2f2 Mon Sep 17 00:00:00 2001 From: Leo Li Date: Mon, 19 Oct 2026 22:04:57 +0000 Subject: [PATCH 12/26] test(changelog): no internal line of the 50 published nightlies reaches the page groups (failing) Co-Authored-By: Claude Opus 5.5 --- webviews/test/changelog-readable.test.ts | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/webviews/test/changelog-readable.test.ts b/webviews/test/changelog-readable.test.ts index 218a3e47701e..b49cc73ca70a 100644 --- a/webviews/test/changelog-readable.test.ts +++ b/webviews/test/changelog-readable.test.ts @@ -77,6 +77,17 @@ const USER_FACING = [ "feat: a naïve-mode-switch for the prompt", ]; +// The 49-nightly range showed "Restore the URL chip hover card styles lost in the Chief Dock squash" +// under Fixed: its digest title was cut before "squash", and only the whole line reads as internal. +test("no internal line of the 50 published nightlies reaches New, Improved or Fixed", () => { + const all = nightlies as ReleaseNotes[]; + for (const notes of [all, ...all.map((n) => [n])]) { + const view = mergedView(notes, "en"); + for (const row of [view.hero, ...view.groups.flatMap((g) => g.items)].filter((i) => i !== undefined)) + expect(`${row.title} ${row.summary}`).not.toMatch(/export-backdrop-art|#N\b|#21369|Chief Dock squash/i); + } +}); + test("hyphenated feature names, small numbers and squash commits stay user-facing", () => { for (const subject of USER_FACING) expect([subject, readableChange(subject).internal]).toEqual([subject, false]); }); From cfbba2f7f6f26e095e0eefcc327505eefcb38c78 Mon Sep 17 00:00:00 2001 From: Leo Li Date: Mon, 19 Oct 2026 22:05:29 +0000 Subject: [PATCH 13/26] fix(changelog): a machine entry made whole from its line is judged internal on the whole line MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit "Restore the URL chip hover card styles lost in the Chief…" lost the word that marks it internal when the digest cut it; the page now judges the line it makes the title whole from. Co-Authored-By: Claude Opus 5.5 --- webviews/src/pages/changelog/model.ts | 2 ++ webviews/src/pages/changelog/readableChange.ts | 3 ++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/webviews/src/pages/changelog/model.ts b/webviews/src/pages/changelog/model.ts index fb9260400273..8c849fee49b4 100644 --- a/webviews/src/pages/changelog/model.ts +++ b/webviews/src/pages/changelog/model.ts @@ -146,6 +146,8 @@ function readableItem(item: ReleaseItem, changes: ChangeItem[], machine: boolean .map((c) => readableChange(c.title).title) .find((text) => !text.endsWith("…") && stemOf(text).startsWith(stem) && text.length > stem.length); full = whole ?? full.slice(0, -1).trim(); + // The cut title may have dropped the words that mark the line internal ("… the Chief Dock squash"). + if (machine && readableChange(full).internal) return undefined; } let summary = !echoes ? item.summary : lineWhole ? capitalized(titleTail(line, full)) : ""; let title = full; diff --git a/webviews/src/pages/changelog/readableChange.ts b/webviews/src/pages/changelog/readableChange.ts index 21d50902fdd2..487a6dd5977e 100644 --- a/webviews/src/pages/changelog/readableChange.ts +++ b/webviews/src/pages/changelog/readableChange.ts @@ -75,7 +75,8 @@ const CODE_LIKE = three or more hyphenated parts ("export-backdrop-art"; not "two-finger-swipe", "cmd-shift-t", "up-to-date" or "per-tab-zoom"), a pull request number ("#21369", "#N"; not "#1") and a repair after a squash ("lost in the Chief Dock squash"; not "squash commits from the review pane"). */ -const TOOL_NAME = /(?[A-Za-z-]+)(?:\((?[^)]*)\))?!?:\s*(?.+)$/; From 81af7a351f8aa646c85663d0ec81f1ecc1339efa Mon Sep 17 00:00:00 2001 From: Leo Li Date: Mon, 19 Oct 2026 19:15:41 -0700 Subject: [PATCH 14/26] test(changelog): the Updated card lists only readable changes after the base's compact list Co-Authored-By: Claude Opus 5.5 --- webviews/test/update-ready-popover.test.tsx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/webviews/test/update-ready-popover.test.tsx b/webviews/test/update-ready-popover.test.tsx index 577306f8763e..b02c3c1f5d48 100644 --- a/webviews/test/update-ready-popover.test.tsx +++ b/webviews/test/update-ready-popover.test.tsx @@ -168,6 +168,8 @@ test("the popup and the card read notes published before the readable rules as t "Keep the Mac awake while agents work", ]); expect(host.querySelector(".wn-card-line")).toBeNull(); +}); + // Notes with screenshots (Leo 2026-10-19): a change's picture shows inline at the popover's width, // in the theme's scheme, and a click on it opens the notes, where it shows larger. test("a change's picture shows inline and a click on it opens the notes", async () => { From 57ed1a0642a0413e5370996dca848bba7394d0e6 Mon Sep 17 00:00:00 2001 From: Leo Li Date: Mon, 19 Oct 2026 20:24:29 -0700 Subject: [PATCH 15/26] ci(nightly): the release-notes check runs on a GitHub-hosted runner Nightly jobs never route to Blacksmith (tests/test_ci_nightly_off_blacksmith.py). Co-Authored-By: Claude Opus 5.5 --- .github/workflows/nightly.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml index 505bc9665847..0753565ce583 100644 --- a/.github/workflows/nightly.yml +++ b/.github/workflows/nightly.yml @@ -6352,7 +6352,7 @@ jobs: check-release-notes: needs: [decide, build-nightly-app, sign-release-notes, resolve-nightly-cmux-tui-client] if: "!cancelled() && needs.decide.outputs.track == 'nightly-next' && needs.sign-release-notes.result == 'success'" - runs-on: ${{ github.repository_owner != 'manaflow-ai' && 'ubuntu-24.04' || vars.LINUX_RUNNER || 'blacksmith-4vcpu-ubuntu-2404' }} + runs-on: ubuntu-24.04 timeout-minutes: 10 permissions: contents: read From 8fd01952458dce252f5930d536eb61e8f8f91a09 Mon Sep 17 00:00:00 2001 From: Leo Li Date: Tue, 20 Oct 2026 22:24:33 -0700 Subject: [PATCH 16/26] test(changelog): the Updated card's readable-only check reads base's area rows Base's #22810 turned the card's change list into area rows (.wn-card-areas); the check still reads that only the readable change reaches the card. Agent-Session: 01a15ba2-c7ad-7850-9e71-5b51f1c9ed9f --- webviews/test/update-ready-popover.test.tsx | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/webviews/test/update-ready-popover.test.tsx b/webviews/test/update-ready-popover.test.tsx index 66c3f042bc99..2a7e3e0826ad 100644 --- a/webviews/test/update-ready-popover.test.tsx +++ b/webviews/test/update-ready-popover.test.tsx @@ -164,9 +164,11 @@ test("the popup and the card read notes published before the readable rules as t undefined }} />, ), ); - expect([...host.querySelectorAll(".wn-card-changes li")].map((li) => li.textContent)).toEqual([ - "Keep the Mac awake while agents work", - ]); + // The card summarizes by area (#22810): one row, made only of the readable change. + const rows = [...host.querySelectorAll(".wn-card-areas li")].map((li) => li.textContent ?? ""); + expect(rows).toHaveLength(1); + expect(rows[0]).toMatch(/keep the mac awake while agents work/i); + expect(rows[0]).not.toMatch(/perf-fanout|backdrop/i); expect(host.querySelector(".wn-card-line")).toBeNull(); }); From 2f4c7cdc2cdb5a32e361832873cdeecf13eabcdd Mon Sep 17 00:00:00 2001 From: Leo Li Date: Tue, 20 Oct 2026 22:48:42 -0700 Subject: [PATCH 17/26] test(changelog): a summary line the page would fold warns but does not block the notes (failing) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Review of #22099: the page re-reads release-notes.py's readable summary lines, and a few read as internal the second time ("Merge the green pull request…", "Onboarding: …"). The page folds them, so no internal work reaches people, but the check failed and would withhold every later nightly. Agent-Session: 01a15ba2-c7ad-7850-9e71-5b51f1c9ed9f --- webviews/test/changelog-notes-check.test.ts | 22 ++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/webviews/test/changelog-notes-check.test.ts b/webviews/test/changelog-notes-check.test.ts index af9b6b72d08a..0d1248b0c5da 100644 --- a/webviews/test/changelog-notes-check.test.ts +++ b/webviews/test/changelog-notes-check.test.ts @@ -4,7 +4,7 @@ // notes index listed on 2026-10-19, as published. import { expect, test } from "bun:test"; import fixture from "../src/pages/changelog/fixtures/nightly-next-50.json"; -import { checkNightlyNotes } from "../src/pages/changelog/notesCheck"; +import { blocksPublish, checkNightlyNotes } from "../src/pages/changelog/notesCheck"; import type { ReleaseNotes, WhatsNewEntry } from "../src/pages/changelog/types"; const nightlies = fixture as ReleaseNotes[]; @@ -159,3 +159,23 @@ test("the command fails with one annotation per defect, and passes clean notes", "3917159104301: notes, page (1 and 10 nightlies) and card read clean\n", ]); }); + +// Review of #22099: the page re-reads a summary line release-notes.py already made readable, and +// a few such lines read as internal the second time ("Merge the green pull request…" from +// "cx-ncc.77.4: merge the green pull request…"; "Onboarding: …" from "onboarding (red): …"). +// The page folds those lines, so no internal work reaches people; that must not withhold the +// night's notes (and every nightly after it, which carries the same line). +test("a summary line the page would fold warns but does not block the notes", () => { + const { notes, previous } = at("3917159104301"); + const folded = [ + "Merge the green pull request from the PR chip", + "Onboarding: the primary button must never be the theme's blue", + ]; + const built = { + ...clean(notes), + summary: [...(clean(notes).summary ?? []), ...folded.map((title) => ({ title, group: "fixed" as const }))], + }; + const defects = checkNightlyNotes(built, previous); + expect(defects.filter((d) => d.kind === "internal").map((d) => d.text)).toEqual(folded); + expect(defects.filter(blocksPublish)).toEqual([]); +}); From 54e0cf40676d73c89bde69a9f27d9ca1b83c7055 Mon Sep 17 00:00:00 2001 From: Leo Li Date: Tue, 20 Oct 2026 22:48:54 -0700 Subject: [PATCH 18/26] fix(changelog): internal work among the machine lines warns instead of withholding the notes The page and the card fold a machine line that reads as internal, so none reaches people; the check now annotates it as a warning and fails only on a cut title, a bead id or a title shown twice. Agent-Session: 01a15ba2-c7ad-7850-9e71-5b51f1c9ed9f --- scripts/cmux-next/check-release-notes.ts | 6 +++--- webviews/src/pages/changelog/notesCheck.ts | 13 +++++++++++-- 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/scripts/cmux-next/check-release-notes.ts b/scripts/cmux-next/check-release-notes.ts index ac4361d3572f..eb17b05a5d1e 100644 --- a/scripts/cmux-next/check-release-notes.ts +++ b/scripts/cmux-next/check-release-notes.ts @@ -2,10 +2,10 @@ // // The nightly-next pre-publish check (nightly.yml check-release-notes): reads this build's notes // the way the What's New page (1 and 10 nightlies) and the update card will show them, and fails -// with one error annotation per defect (webviews/src/pages/changelog/notesCheck.ts). PREVIOUS are +// with one error annotation per defect (internal work among the machine lines only warns) (webviews/src/pages/changelog/notesCheck.ts). PREVIOUS are // the nightlies published before it, newest first. import { readFileSync } from "node:fs"; -import { annotation, checkNightlyNotes, RANGE } from "../../webviews/src/pages/changelog/notesCheck"; +import { annotation, blocksPublish, checkNightlyNotes, RANGE } from "../../webviews/src/pages/changelog/notesCheck"; import type { ReleaseNotes } from "../../webviews/src/pages/changelog/types"; const [path, ...previousPaths] = process.argv.slice(2); @@ -18,5 +18,5 @@ const notes = read(path); const previous = previousPaths.slice(0, RANGE - 1).map(read); const defects = checkNightlyNotes(notes, previous); for (const defect of defects) console.log(annotation(notes.build, defect)); -if (defects.length > 0) process.exit(1); +if (defects.some(blocksPublish)) process.exit(1); console.log(`${notes.build}: notes, page (1 and ${previous.length + 1} nightlies) and card read clean`); diff --git a/webviews/src/pages/changelog/notesCheck.ts b/webviews/src/pages/changelog/notesCheck.ts index f510c702a5a3..b85c96d1545c 100644 --- a/webviews/src/pages/changelog/notesCheck.ts +++ b/webviews/src/pages/changelog/notesCheck.ts @@ -110,6 +110,14 @@ export function cardItems(notes: ReleaseNotes, language: string): UpdateHighligh return readableUpdateItems(picked.slice(0, CARD_ITEMS)); } +/** Whether a defect withholds the notes. Internal work among the machine lines only warns: the + page and the card fold those lines (model.ts readableItem, readableUpdateItems), so none reaches + people, and a line the page reads as internal on a second pass ("Merge the green pull request…") + would otherwise withhold this nightly and every nightly after it. */ +export function blocksPublish(defect: NotesDefect): boolean { + return defect.kind !== "internal"; +} + function same(a: NotesDefect, b: NotesDefect): boolean { return a.kind === b.kind && a.text === b.text; } @@ -141,7 +149,8 @@ const LABELS: Record = { internal: "internal work in New, Improved or Fixed", }; -/** One GitHub Actions error annotation. */ +/** One GitHub Actions annotation: an error for a defect that withholds the notes, else a warning. */ export function annotation(build: string, defect: NotesDefect): string { - return `::error title=Release notes::${build} ${defect.where}: ${LABELS[defect.kind]}: ${defect.text}`; + const level = blocksPublish(defect) ? "error" : "warning"; + return `::${level} title=Release notes::${build} ${defect.where}: ${LABELS[defect.kind]}: ${defect.text}`; } From 141fc74928130de46017be1bf6bdab31fd927951 Mon Sep 17 00:00:00 2001 From: Leo Li Date: Tue, 20 Oct 2026 22:57:50 -0700 Subject: [PATCH 19/26] test(release-notes): the items test expects the digest's full-stop summaries ci-guards now runs release-notes-items.test.sh (this PR); it had been failing unrun since base's digest started ending a summary with a full stop. Same failure at base 26e79e1a848. Agent-Session: 01a15ba2-c7ad-7850-9e71-5b51f1c9ed9f --- scripts/cmux-next/tests/release-notes-items.test.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/cmux-next/tests/release-notes-items.test.sh b/scripts/cmux-next/tests/release-notes-items.test.sh index ff4d2ac6a0c9..5ff0f4e60da0 100755 --- a/scripts/cmux-next/tests/release-notes-items.test.sh +++ b/scripts/cmux-next/tests/release-notes-items.test.sh @@ -47,8 +47,8 @@ assert titles == [ ], titles entries = notes["whatsNew"]["entries"] assert [(e["title"]["en"], e["summary"]["en"]) for e in entries] == [ - ("A column's tab bar lays out for where its pane rests", "Never pinned to the traffic lights while the camera scrolls"), - ("Terminals in the keep-alive band keep drawing", "So a column scrolled in is never blank"), + ("A column's tab bar lays out for where its pane rests", "Never pinned to the traffic lights while the camera scrolls."), + ("Terminals in the keep-alive band keep drawing", "So a column scrolled in is never blank."), ], entries assert not any("…" in e["title"]["en"] for e in entries) print("ok") From 7551ffe604d30f6deb39a5b52430bbe1125718a4 Mon Sep 17 00:00:00 2001 From: Leo Li Date: Thu, 22 Oct 2026 20:11:36 -0700 Subject: [PATCH 20/26] test(changelog): every change after the first three reads as they do, on the popup and the card Red at this commit: the popover renders UpdateHighlights.rest verbatim, so an internal line, a cut title and a repeat reach it (review of #22099 at cb6db8b0). Co-Authored-By: Claude Opus 5.5 Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a15ba2-c7ad-7850-9e71-5b51f1c9ed9f&host=cosmic-gray --- webviews/test/update-ready-popover.test.tsx | 73 +++++++++++++++++++++ 1 file changed, 73 insertions(+) diff --git a/webviews/test/update-ready-popover.test.tsx b/webviews/test/update-ready-popover.test.tsx index 2a7e3e0826ad..3a6747bfb201 100644 --- a/webviews/test/update-ready-popover.test.tsx +++ b/webviews/test/update-ready-popover.test.tsx @@ -172,6 +172,79 @@ test("the popup and the card read notes published before the readable rules as t expect(host.querySelector(".wn-card-line")).toBeNull(); }); +// Review of #22099: the popover's scrolling list (`rest`, every change after the first three) and the +// card's summary read through the same rules as the first three. An internal line, a title cut with +// "…" and a repeat of a change already shown never reach either surface. +test("every change after the first three reads as the first three do, on the popup and the card", async () => { + const { createRoot } = await import("react-dom/client"); + const { UpdateReadyHighlights, UpdatedCard } = await import("../src/pages/changelog/UpdateSurfaces"); + const { createStrings } = await import("../src/pages/shared/i18n"); + const table = (await import("../src/pages/changelog/generated/strings.json")).default; + const data = { + version: "1.0.0-nightly.3917159104301", + build: "3917159104301", + fromVersion: "1.0.0-nightly.3917061587901", + fromBuild: "3917061587901", + date: "2026-10-19", + source: "summary" as const, + language: "en", + items: [ + { + id: "summary-0", + title: "Keep the Mac awake while agents work", + summary: null, + category: "fixed" as const, + }, + ], + rest: [ + { + id: "summary-3", + title: "Cmux NEXT perf-fanout: a restored New Tab page reads no tab…", + summary: "Cmux NEXT perf-fanout: a restored New Tab page reads no tab list in its pane's snapshot", + category: "improved" as const, + }, + { + id: "summary-4", + title: "Terminals show background art through the glass, like the…", + summary: "Terminals show background art through the glass, like the other panes", + category: "improved" as const, + }, + { + id: "summary-5", + title: "Keep the Mac awake while agents work", + summary: null, + category: "fixed" as const, + }, + ], + moreCount: 3, + changelog: { from: "1.0.0-nightly.3917061587901", to: "1.0.0-nightly.3917159104301" }, + }; + act(() => root?.unmount()); + root = createRoot(host); + await act(async () => + root!.render( + undefined }} />, + ), + ); + const rest = [...host.querySelectorAll(".wn-pop-rest li")].map((li) => li.textContent ?? ""); + expect(rest).toHaveLength(1); + expect(rest[0]).toMatch(/^Terminals show background art through the glass/); + expect(rest[0]).not.toContain("…"); + const text = host.textContent ?? ""; + expect(text).not.toMatch(/perf-fanout/i); + expect(text.split("Keep the Mac awake while agents work").length - 1).toBe(1); + act(() => root?.unmount()); + root = createRoot(host); + await act(async () => + root!.render( + undefined }} />, + ), + ); + const card = host.textContent ?? ""; + expect(card).not.toMatch(/perf-fanout/i); + expect(card).not.toContain("…"); +}); + // Notes with screenshots (Leo 2026-10-19): a change's picture shows inline at the popover's width, // in the theme's scheme, and a click on it opens the notes, where it shows larger. test("a change's picture shows inline and a click on it opens the notes", async () => { From eefc2fd64fb04d80eccd39cca62e2d0d0f82d28d Mon Sep 17 00:00:00 2001 From: Leo Li Date: Thu, 22 Oct 2026 20:11:39 -0700 Subject: [PATCH 21/26] fix(changelog): the popup's rest list and the card's summary read through the readable rules readableUpdate() cleans items and rest together, dropping internal lines, restoring cut titles and dropping repeats of a change already shown; UpdateReadyHighlights and UpdatedCard's offline fallback both use it. Co-Authored-By: Claude Opus 5.5 Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a15ba2-c7ad-7850-9e71-5b51f1c9ed9f&host=cosmic-gray --- webviews/src/pages/changelog/UpdateSurfaces.tsx | 11 +++++------ webviews/src/pages/changelog/model.ts | 13 ++++++++++++- 2 files changed, 17 insertions(+), 7 deletions(-) diff --git a/webviews/src/pages/changelog/UpdateSurfaces.tsx b/webviews/src/pages/changelog/UpdateSurfaces.tsx index 41a1668ff66d..70669d8d363a 100644 --- a/webviews/src/pages/changelog/UpdateSurfaces.tsx +++ b/webviews/src/pages/changelog/UpdateSurfaces.tsx @@ -21,7 +21,7 @@ import { useEffect, useId, useRef, useSyncExternalStore } from "react"; import { CARD_SCROLL_ATTRIBUTE, installScrollEdges } from "../../scrollers"; import { getColorScheme, subscribeColorScheme } from "./colorScheme"; -import { distinctSummary, readableUpdateItems } from "./model"; +import { distinctSummary, readableUpdate } from "./model"; import type { Strings } from "../shared/i18n"; import type { ReleaseNotes } from "./types"; import type { UpdateHighlightMedia, UpdateHighlights, UpdateSurfaceActions } from "./updateHighlights"; @@ -68,9 +68,7 @@ export function UpdatedCard({ actions: UpdateSurfaceActions; }) { const titleId = useId(); - const summary = span - ? summarizeUpdate(span, strings.language) - : summarizeHighlights({ ...data, items: readableUpdateItems(data.items) }); + const summary = span ? summarizeUpdate(span, strings.language) : summarizeHighlights(readableUpdate(data)); const empty = strings.t(span ? "changelog.page.maintenance" : "updates.card.whatsNewInBuild"); return (
    @@ -125,8 +123,9 @@ export function UpdateReadyHighlights({ }) { const titleId = useId(); const scroller = useRef(null); - const items = readableUpdateItems(data.items); - const rest = data.rest ?? null; + const readable = readableUpdate(data); + const items = readable.items; + const rest = readable.rest ?? null; useEffect(() => (scroller.current ? installScrollEdges(scroller.current) : undefined), [data]); return (
    diff --git a/webviews/src/pages/changelog/model.ts b/webviews/src/pages/changelog/model.ts index 51744b58c07a..4f5c8fd5753c 100644 --- a/webviews/src/pages/changelog/model.ts +++ b/webviews/src/pages/changelog/model.ts @@ -12,7 +12,7 @@ import type { WhatsNewEntry, } from "./types"; import { subjectArea, type AreaKey } from "./areas"; -import type { UpdateHighlightItem } from "./updateHighlights"; +import type { UpdateHighlightItem, UpdateHighlights } from "./updateHighlights"; import { readableChange, revertedSubject, shortTitle, tidyTitle, titleTail } from "./readableChange"; export const CATEGORY_ORDER: readonly WhatsNewCategory[] = ["new", "improved", "fixed", "security"]; @@ -197,6 +197,17 @@ export function readableUpdateItems(items: UpdateHighlightItem[]): UpdateHighlig }); } +/** The whole update as the card and popover read it: `items` and every change after them (`rest`) + through the same rules, so no internal or cut line reaches the popover's list or the card's + summary (review of #22099). A change in `rest` that repeats one shown above drops; `moreCount` + keeps counting the changes the host did not send. */ +export function readableUpdate(data: UpdateHighlights): UpdateHighlights { + const items = readableUpdateItems(data.items); + if (!data.rest) return { ...data, items }; + const rest = readableUpdateItems([...data.items, ...data.rest]).slice(items.length); + return { ...data, items, rest, moreCount: Math.max(0, data.moreCount - (data.rest.length - rest.length)) }; +} + function stemOf(text: string): string { return text.replace(/[.!…\s]+$/u, "").toLowerCase(); } From bbb9b39de43ca094535472e61528dada4ff97167 Mon Sep 17 00:00:00 2001 From: Leo Li Date: Thu, 22 Oct 2026 20:19:41 -0700 Subject: [PATCH 22/26] nightly: the release notes check names its pull-request counterpart; the 50-nightly fixture names no fleet host check-release-notes runs notesCheck.ts, which webviews/test/changelog-notes-check.test.ts covers in ci-web.yml's Test webviews. The fixture's quoted titles said Huge Blue and cmux-lawrence-2; they now say build-box and studio-mac (check-fixture-host-names.py). Co-Authored-By: Claude Opus 5.5 Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a15ba2-c7ad-7850-9e71-5b51f1c9ed9f&host=cosmic-gray --- .github/nightly-step-coverage.json | 2 ++ .../src/pages/changelog/fixtures/nightly-next-50.json | 8 ++++---- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/.github/nightly-step-coverage.json b/.github/nightly-step-coverage.json index e015b31c7839..5b63552060ed 100644 --- a/.github/nightly-step-coverage.json +++ b/.github/nightly-step-coverage.json @@ -232,6 +232,8 @@ "Start the span at the newest published notes": {"pr": "ci-guards.yml:workflow-guard-tests:Test What's New highlights and release notes"}, "Fetch the commits since the newest published notes": {"pr": "ci-guards.yml:workflow-guard-tests:Validate the nightly-next release notes fetch (published span only)"}, "Build and sign the release notes": {"nightly_only": "signs notes with content key"}}, + "check-release-notes": { + "Check this build's notes as the page and the update card show them": {"pr": "ci-web.yml:react-apps-check-shard:Test webviews", "note": "check-release-notes.ts runs notesCheck.ts, tested by webviews/test/changelog-notes-check.test.ts"}}, "publish-release-notes": { "Recheck the NEXT publication head": {"nightly_only": "reads live published tag, feed"}, "Upload the signed release notes to R2": {"nightly_only": "uploads signed notes to R2"}}, diff --git a/webviews/src/pages/changelog/fixtures/nightly-next-50.json b/webviews/src/pages/changelog/fixtures/nightly-next-50.json index cd6e29371049..5760935568b7 100644 --- a/webviews/src/pages/changelog/fixtures/nightly-next-50.json +++ b/webviews/src/pages/changelog/fixtures/nightly-next-50.json @@ -3481,7 +3481,7 @@ { "author": "Austin Wang", "pr": 21365, - "title": "feat(cloud): read-only Huge Blue app-server inspection route" + "title": "feat(cloud): read-only build-box app-server inspection route" }, { "author": "Leo", @@ -3493,7 +3493,7 @@ "summary": [ { "group": "new", - "title": "Read-only Huge Blue app-server inspection route" + "title": "Read-only build-box app-server inspection route" }, { "group": "changed", @@ -5584,7 +5584,7 @@ }, { "author": "Lawrence Chen", - "title": "sidebar-v2 record script: --stress workspaces are made with --empty (no terminal each: hitch11 started ~790 terminal hosts and used every PTY on cmux-lawrence-2); stops after 20 creates if the PTY count still grows; at the end ends the tag's terminal hosts with stop_tag_daemon.py and prints the PTY count before and after" + "title": "sidebar-v2 record script: --stress workspaces are made with --empty (no terminal each: hitch11 started ~790 terminal hosts and used every PTY on studio-mac); stops after 20 creates if the PTY count still grows; at the end ends the tag's terminal hosts with stop_tag_daemon.py and prints the PTY count before and after" }, { "author": "Lawrence Chen", @@ -5628,7 +5628,7 @@ }, { "author": "Lawrence Chen", - "title": "sidebar-v2 record script: Instruments writes its ktrace intermediates to a per-run TMPDIR that is deleted once the .trace is exported (and at exit); unopened instruments*.ktrace files born during this run's trace in the user temp dir are deleted too (they filled cmux-lawrence-2's disk)" + "title": "sidebar-v2 record script: Instruments writes its ktrace intermediates to a per-run TMPDIR that is deleted once the .trace is exported (and at exit); unopened instruments*.ktrace files born during this run's trace in the user temp dir are deleted too (they filled studio-mac's disk)" }, { "author": "Lawrence Chen", From 1fef20f45ebaac975624810a16ab7b56b1b1fbeb Mon Sep 17 00:00:00 2001 From: Leo Li Date: Thu, 22 Oct 2026 20:55:20 -0700 Subject: [PATCH 23/26] test(changelog): an update of internal work only offers See release notes Red at this commit: the footer counts the raw items, so it says See all changes over an empty popup (review of #22099 at eefc2fd6). Co-Authored-By: Claude Opus 5.5 Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a15ba2-c7ad-7850-9e71-5b51f1c9ed9f&host=cosmic-gray --- webviews/test/update-ready-popover.test.tsx | 31 +++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/webviews/test/update-ready-popover.test.tsx b/webviews/test/update-ready-popover.test.tsx index 3a6747bfb201..446ccb8ee742 100644 --- a/webviews/test/update-ready-popover.test.tsx +++ b/webviews/test/update-ready-popover.test.tsx @@ -366,3 +366,34 @@ test("without a change list the hover card shows the versions and See release no await act(async () => link!.click()); expect(opened).toBe(1); }); + +// Review of #22099: the footer counts what the popup shows. Only internal work: no list, so it +// offers the release notes, not "See all changes" of nothing. +test("an update whose every change is internal offers See release notes, not See all changes", async () => { + const { createRoot } = await import("react-dom/client"); + const { UpdateReadyHighlights } = await import("../src/pages/changelog/UpdateSurfaces"); + const { createStrings } = await import("../src/pages/shared/i18n"); + const table = (await import("../src/pages/changelog/generated/strings.json")).default; + act(() => root?.unmount()); + root = createRoot(host); + const data = { + ...readyData([]), + source: "summary" as const, + items: [ + { + id: "summary-0", + title: "Export-backdrop-art reads each entry's subject box and…", + summary: "Export-backdrop-art reads each entry's subject box and exports it", + category: "improved" as const, + }, + ], + }; + await act(async () => + root!.render( + undefined }} />, + ), + ); + expect(host.querySelector(".wn-pop-list")).toBeNull(); + expect(host.querySelector(".wn-pop-all")?.textContent).toContain("See release notes"); + expect(host.textContent).not.toContain("See all changes"); +}); From 52db65c18fe02ab470158300abc00b47753333a5 Mon Sep 17 00:00:00 2001 From: Leo Li Date: Thu, 22 Oct 2026 20:55:23 -0700 Subject: [PATCH 24/26] fix(changelog): the popup's footer counts the changes it shows Co-Authored-By: Claude Opus 5.5 Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a15ba2-c7ad-7850-9e71-5b51f1c9ed9f&host=cosmic-gray --- webviews/src/pages/changelog/UpdateSurfaces.tsx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/webviews/src/pages/changelog/UpdateSurfaces.tsx b/webviews/src/pages/changelog/UpdateSurfaces.tsx index 70669d8d363a..188e7aaee9ea 100644 --- a/webviews/src/pages/changelog/UpdateSurfaces.tsx +++ b/webviews/src/pages/changelog/UpdateSurfaces.tsx @@ -181,7 +181,9 @@ export function UpdateReadyHighlights({ {strings.format("updates.card.more", String(data.moreCount))} )} From a3072c2b376217c001c80bffab5073e18a1418c6 Mon Sep 17 00:00:00 2001 From: Leo Li Date: Thu, 22 Oct 2026 20:55:26 -0700 Subject: [PATCH 25/26] nightly: a feed that does not serve an earlier nightly's notes fails the notes check The check compares this build with the nine before it; a narrowed set could pass a duplicate across nightlies, so it holds the notes like a bad index does (review of #22099). Co-Authored-By: Claude Opus 5.5 Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a15ba2-c7ad-7850-9e71-5b51f1c9ed9f&host=cosmic-gray --- .github/workflows/nightly.yml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml index 59b57150ca7c..4fb3b0dd18df 100644 --- a/.github/workflows/nightly.yml +++ b/.github/workflows/nightly.yml @@ -6990,9 +6990,11 @@ jobs: fi previous+=("$file") done <<< "$builds" - # A feed outage narrows the wider page; say so instead of passing it as 10 nightlies. + # A feed outage would narrow the wider page and could pass a duplicate across nightlies, so + # it fails the check (and holds the notes) like a bad index does; a rerun checks again. if [ "${#missing[@]}" -gt 0 ]; then - echo "::warning title=Release notes::$NIGHTLY_BUILD: the wider page lacks ${#missing[@]} nightlies the feed did not serve: ${missing[*]}" + echo "::error title=Release notes::$NIGHTLY_BUILD: the feed did not serve ${#missing[@]} of the nightlies the check compares with: ${missing[*]}" + exit 1 fi bun scripts/cmux-next/check-release-notes.ts "notes/$NIGHTLY_BUILD.json" "${previous[@]}" From 1332461e60dd488e8a6bde30b52996d4d71dea0a Mon Sep 17 00:00:00 2001 From: Leo Li Date: Thu, 22 Oct 2026 21:51:55 -0700 Subject: [PATCH 26/26] ci-guards: the release notes items step runs after an earlier red guard (!cancelled()) Co-Authored-By: Claude Opus 5.5 Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a15ba2-c7ad-7850-9e71-5b51f1c9ed9f&host=cosmic-gray --- .github/workflows/ci-guards.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci-guards.yml b/.github/workflows/ci-guards.yml index 6abff08f47f3..66fdb3e1e587 100644 --- a/.github/workflows/ci-guards.yml +++ b/.github/workflows/ci-guards.yml @@ -1418,7 +1418,7 @@ jobs: run: python3 tests/test_nightly_next_release_notes_fetch.py - name: Validate the nightly-next release notes items, summary and digest - if: ${{ matrix.group == 'release-notary' }} + if: ${{ !cancelled() && matrix.group == 'release-notary' }} run: bash scripts/cmux-next/tests/release-notes-items.test.sh - name: Validate the nightly cmux-tui resolver (newest published tree, no wait)