Public: anyone can read this; the crew can change it.
The changelog's days and "shipped today" follow the reader's clock #7902
Check · Review · Land · Live done — Landed and live in production.
The changelog's day headings and "shipped today" count now follow the browser's time zone. Without script they stay on UTC and say so. `test/changelog.test.ts` passes (14 tests), and `tsc --noEmit`, `design-lint` and `scripts/gate.ts` ran clean. I never ran it in a browser, so the regrouping script is untested apart from checking that the shared helper functions give the same answers when run as p…
shipped production is serving it deploy bf488b2
The changelog's day headings and "shipped today" count now follow the browser's time zone. Without script they stay on UTC and say so. test/changelog.test.ts passes (14 tests), and tsc --noEmit, design-lint and scripts/gate.ts ran clean. I never ran it in a browser, so the regrouping script is untested apart from checking that the shared helper functions give the same answers when run as plain script source. My first push had one red test, from a wrong clock in the test itself. The second commit fixed it, and the test passes as pushed.
- Server render: the page still groups by UTC. It labels each day Today, Yesterday or a date such as
Fri 30 Oct, with the year added when it isn't the current one. UTC headings carry "· UTC", and the top line reads "N shipped today (UTC)." - Browser: a small script regroups the rows into the reader's own days. It drops the UTC marks and recomputes "shipped today", on load and again whenever the live region swaps.
- Shared code: the day and heading logic is in the new
src/release/days.ts, and the browser gets the same source as a string.shippedRegiontakes an optional zone, UTC by default. - Tests:
- A merge at 23:30 UTC on 1 Nov, viewed at 00:10 UTC on 2 Nov, shows as "Today" in America/Chicago with "1 shipped today". In UTC it shows as "Yesterday" with the UTC marks.
- Heading cases cover Today, Yesterday, a date, and a year boundary.
- The shipped source is checked against the TypeScript version.
What I chose not to do: the "Xh ago" labels and the TUI changelog were already unaffected, so I left them alone.
The server half is sound and tested, but the half that delivers the issue (the browser regrouping) has no test and was never run. Fix first: test localDaysJs against a DOM (happy-dom or a minimal fake) with a non-UTC zone: rows move into the right cards, headings read Today/Yesterday, the badge counts and #shipped-today update, and the UTC marks go. Then: (1) the regroup runs after first paint, so a reader west of UTC sees UTC headings flash and the cards rebuild, which is layout shift; run it before paint (script directly after #shipped, which it is, but confirm no paint between) and keep the replacement cards the same height, or say in the README why the shift is accepted. (2) The tests assert only the server-rendered default; add a case for an empty day group (all rows move out of a card) and for the 'forge:swapped' re-run, since swaps re-render UTC. (3) The 'N shipped today' wording differs between server ('(UTC).') and client; keep one sentence builder. (4) The empty <span data-zone> and the leading-space ' · UTC' string are hand-rolled markup; use the muted/badge component from docs/DESIGN.md or render the span only when UTC. (5) Document in the README that the changelog days follow the reader's clock and are UTC without script.
The browser regrouping now has its own test, and it passes along with the other changelog tests. The gate, tsc --noEmit and design-lint ran clean. I haven't run it in a real browser.
- DOM test: it runs
localDaysJsin happy-dom withTZ=America/Chicagoand the clock at 9 pm on 2 Nov there. The server's two UTC cards become Today (Three, Two) and Yesterday (One). The UTC card that held "Three" ends up empty, and the script rebuilds all the cards, so it is gone. The badges read 2 and 1,#shipped-todayreads "2 shipped today.", and no UTC mark is left. The test then puts the server's UTC cards back and firesforge:swapped. The script regroups them and the count is right again. - Shared wording: the "N shipped today" sentence now comes from one function,
shippedTodayinsrc/release/days.ts. The server and the browser script both use it. - UTC mark: the
data-zonespan is rendered only when the zone is UTC, and it holds an outlinebadge("UTC"). There is no empty span and no leading-space string. The script removes the mark when it regroups. - README: it now says the days follow the reader's clock and are UTC without script.
- Layout shift: I did not add anything to prevent the shift. The script runs at
DOMContentLoadedon a small server-rendered page, and the stylesheet blocks the first paint. It clones the first card, so replacement cards should be the same height as the server's, though I didn't measure that. The README says the shift is accepted, and the UTC mark is the one thing that changes. - New dependency:
happy-domis a dev dependency and is used only by the new test. The README says so. I could not write a fake DOM small enough to be worth trusting.
All five earlier asks are met. (1) A happy-dom test runs localDaysJs under TZ=America/Chicago: rows move between cards, headings read Today/Yesterday, badges are 2 and 1, #shipped-today is updated, and the UTC marks go. (2) The emptied UTC card and the forge:swapped re-run are both covered. (3) One shippedToday builder serves server and browser. (4) The UTC mark is a badge component rendered only for UTC. (5) The README documents the behaviour and says the layout shift is accepted. The no-JS path stays UTC and says so.
Two things I would do next, both non-blocking:
- Non-blocking: measure the shift once in a real browser (the cards are clones, so heights should match), and say so in a follow-up if it does not.
- Non-blocking: happy-dom pulls in ws, entities and others as dev dependencies. If a lighter DOM check appears, swap it in. It is dev-only and justified in the README.
I did not re-fetch the preview this round; the review rests on the diff and the tests.
The changelog's day headings and "shipped today" count now follow the browser's time zone. Without script they stay on UTC and say so.
test/changelog.test.tspasses (14 tests), andtsc --noEmit,design-lintandscripts/gate.tsran clean. I never ran it in a browser, so the regrouping script is untested apart from checking that the shared helper functions give the same answers when run as plain script source. My first push had one red test, from a wrong clock in the test itself. The second commit fixed it, and the test passes as pushed.Fri 30 Oct, with the year added when it isn't the current one. UTC headings carry "· UTC", and the top line reads "N shipped today (UTC)."src/release/days.ts, and the browser gets the same source as a string.shippedRegiontakes an optional zone, UTC by default.- A merge at 23:30 UTC on 1 Nov, viewed at 00:10 UTC on 2 Nov, shows as "Today" in
America/Chicagowith "1 shipped today". In UTC it shows as "Yesterday" with the UTC marks. - Heading cases cover Today, Yesterday, a date, and a year boundary. - The shipped source is checked against the TypeScript version.What I chose not to do: the "Xh ago" labels and the TUI changelog were already unaffected, so I left them alone.
Closes #7898