cmux NEXT: the Updated card names the build by its time and commit, and how far it is from the newest
Summary
Leo, on the cmux NEXT Updated card: "Like with this new update, I don't know what update this is, but, like, it just says updated to nightly, but that doesn't mean anything." The card said "Updated to Nightly · Oct 26", and the build ("1.0.0-nightly.4037004604601") showed only in a tooltip.
The card now says which build you are on:
- When it was made, in your time zone and locale: "Updated to Nightly · Oct 26, 7:38 PM" (en-GB reads "26 Oct, 19:38"). Before, it showed only a UTC day. The full version stays in the tooltip. In a narrow sidebar the line wraps between its parts and nothing is cut off.
- Which build, and how far it is from the newest: a second line, "Build a9d1434 · 2 builds behind newest", "· 1 build behind newest" or "· Newest". It names the build by the short commit it was cut from, or by the build number when the notes don't give the commit.
Where the data comes from:
release-notes.pynow writesbuiltAt(UTC, to the second) into each build's notes. SwiftReleaseNotesdecodesheadandbuiltAt.UpdateHighlightscarries both to the page; when the notes lackbuiltAt, it uses the appcast item's date. The date the notes give is only a day (UTC midnight), so it is never shown as a time. An update record saved before this change takes the time from its staged appcast date.- "Behind newest" comes from the notes index (
cmux.changelog.list), which the card already loads to sum up the update's span. This adds no network call. The line shows the position only once the index has loaded and lists the build; until then, or offline, it shows only "Build a9d1434". - 4 new strings in
webviews/src/pages/changelog/Localizable.xcstrings, in all 21 languages, like their neighbours. This catalog has no plural forms, so languages with number agreement use a "Newer builds: N" form.
Proof
Gallery pages.changelog.update-surfaces: before is the merge-base and after is this head. Fixture data only.
| Before | After |
|---|---|
![]() | ![]() |
![]() | ![]() |
The newest build: 
The gallery renders in CI's DejaVu Sans at the card's minimum width, so its lines wrap more than they do in the app's system font.
No capture: no native scene or tour shows the Updated card with published notes. debug.updater updated on a capture build has no notes for its own build. The card is a web view, and the gallery renders the same component.
Testing
- Red, at the tests-only commit 8d9a5d13b72: the new card, notes and
UpdateHighlightstests fail. - Green, at the head (
cmux-ci test --setup webviews):updated-card-lists-changespasses under TZ=UTC, Asia/Kolkata, Pacific/Kiritimati and America/Los_Angeles. 46 tests pass across the other card and changelog suites (updated-card-summary,update-ready-popover,changelog-model,changelog-readable,whats-new-by-area,changelog-first-paint,whats-new-no-hover-previews,whats-new-text-selection). Also clean:vp fmt --check,tsc,check:catalog-keys,check:design-tokens,check:type-scale, andtests/test_cmux_next_release_notes.py(18). - Swift:
UpdateHighlightsBuildTimeTestscovers the time and commit from the notes, the appcast time as fallback, a day from the notes that is not taken as a time, and older notes and records still decoding. The app compiles on the fleet (cmux-ci compile-check --app); the Swift tests run in this PR's CI.
Observed / Not run
- Not run: the real app on an updated nightly. Notes published before this change have no
builtAt, so until a new nightly publishes, the time comes from the staged appcast item.
Changelog
Changed: The Updated card says when the build was made, in your time zone, which build it is, and how far it is from the newest
Risk: normal. Display only, plus two new optional fields in the notes and in UpdateHighlights. Older notes and saved records decode unchanged.
Agent session: agent session
🤖 Generated with Claude Code



