Repository navigation
test(core): pin the OUT-of-window precedence pair formatDate(V, 'relative', { style: 'short' }) - #8353
Merged
os-justin merged 2 commits intoSep 7, 2026
Conversation
…tive', { style: 'short' })
objectui#7745 pinned "positional wins; `options.style` is read only when the
positional slot is `undefined`", but its sharpest pair was measured only
INSIDE the ±7-day relative window, where `formatDate(v, 'relative', …)`
produces the phrase locally and never reaches the absolute fallback.
Outside the window the same call round-trips through `formatRelativeDate` and
back into `formatDate`, carrying the shared options bag — a second site at
which the losing spelling could take effect, and one the in-window case cannot
reach. This adds that half: the call renders the default absolute face
(`Jul 4, 2024`, `en-US`), not the `style: 'short'` face.
Test-only; no behaviour change. objectui#7816 was ruled A (`formatRelativeDate`
stays style-less), so nothing lands on the relative path.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YBWFb5YgMU5dw8p2VKj16S
`scripts/check-changeset-presence.mjs` counts any file under a released
package's `src/` — `__tests__` included — so a test-only change still owes a
declaration. Empty frontmatter is the gate's own explicit exemption.
Verdict line after adding it:
✅ 1 source file(s) of 1 released package(s) changed, and this change
declares 1 changeset(s) ... Every one of them has an EMPTY frontmatter
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YBWFb5YgMU5dw8p2VKj16S
Contributor
✅ Console Performance Budget
The eager closure is every chunk the entry reaches through static imports — what the browser fetches and parses before the app renders. The entry chunk on its own is a small fraction of it. 📦 Bundle Size Report
Size Limits
|
os-justin
marked this pull request as ready for review
September 7, 2026 14:39
os-justin
deleted the
claude/issue-8262-relative-out-of-window-precedence-pin
branch
September 7, 2026 14:57
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #8262
Test-only. No source file changes, no rendered face moves.
What the pin asserts
One new case in
packages/core/src/utils/__tests__/date-display.optionsStyle-7745.test.ts, in theexisting
the precedence between the two spellings is pinned: positional wins (#7745)describe:Why that is a reading and not a snapshot: #7745's sharpest pair was measured only inside the
±7-day window, where
formatDate(v, 'relative', ...)produces the phrase locally and never reachesthe absolute fallback. Outside the window the same call round-trips through
formatRelativeDateand back into
formatDate, carrying the shared options bag the whole way — a second site at whichthe losing spelling can take effect, and the one the in-window case structurally cannot see.
Assertion shape: the TZ-free equivalence first (
=== formatDate(V, undefined, { locale })), then theliteral anchor, then the named loser with its own lit control immediately before it, so the
not.toBecannot pass against a face that renders nothing.Ablation — two legs, both restored BY STATE
Every leg mutates the read site in
packages/core/src/utils/date-display.ts, never the pin, andruns from a committed implementation. Restore is
git checkout HEAD -- PATHunder atrap ... EXIT INT TERMwith absolute paths; proof isgit diff HEADempty and the blob hashback to
git rev-parse HEAD:PATH, never an exit code.HEADblob ofdate-display.ts(both legs):6cbabb21ccb0eb105722aaaf87b5185b3bfebd2cLeg C — drop the strip (
:152,absoluteFallbackOptions(options)tooptions)Mutated blob
e46f7f1fce2bdece1be4d9ccdcf493d22fd6970b. On-disk proof: anchor count 1 to 0,injected count 0 to 1. Verdict
Tests 4 failed | 11 passed (15). Red by name:... > the options spelling IS the positional spelling, for every face(RangeError, recursion)... > beats it OUT of window too — on the delegated absolute face (#8262)(new)... > ignores it on the out-of-window ABSOLUTE fallback too... > does not recurse when the bag carries style: 'relative'AssertionError: expected 'Jul 4, \'24' to be 'Jul 4, 2024'— the leak, exactly as #7816 recorded it.... > beats it on the sharpest pair(the in-window case) stays GREEN, which is the point.Leg P — invert the precedence (
:203,style ?? options?.styletooptions?.style ?? style)Mutated blob
3ae103e49dd4894f5788eb89e5241090da341a61; same on-disk proof.Verdict
Tests 4 failed | 11 passed (15). Red by name: the four cases of the precedence describe,including the new one. The entire
formatRelativeDate still does not read styledescribe staysGREEN — the strip neutralises
stylebefore the delegated call, so those rows cannot see this half.The result the two legs give together
Leg C reds and leg P reds intersect in exactly one case: the new one. No existing row in the file
is red in both. That is the new case's whole claim — it is anchored to the conjunction of the
precedence and the strip, which is what "two-sided" means here, and it is the row that survives as a
trip-wire if #7816 is ever reopened and the strip flipped (the seat doing that legitimately rewrites
the
formatRelativeDaterows; this one is not in that blast radius by name).Correction against the card
#8262's body says leg C makes the call render
Jul 4, '24"and no existing test goes red".Measured false: leg C turns three existing rows red on current
main, and #7816's own bodyalready recorded that (
It turned three cases red). The true and stronger statement is theintersection above. The card's conclusion survives the correction; its stated evidence does not.
Scope
SCOPE FENCE(packages/fields/src/__tests__/fields-date-widget-convention-8194.test.tsx:285)fences the two readonly
datetimewidget sites whose home isformatDateTime. This PR is@object-ui/core'sformatDateprecedence and touches nopackages/fieldsfile and noformatDateTimeface. Not crossed.mainrenders today, measured.Locale and timezone
localeis fixed explicitly in the fixture (en-US, the file's existingL).TZ is an input here and the repo pins none — no
TZinvitest.config.mts, in anyvitest.setup.*, inturbo.json, inpackage.json, or in any workflow (zero hits; lit control onthe same corpus fires). CI and this container both resolve
UTC.Vis07:00:00.000Zand everyface in the module is built from local date parts, so the literal reads
Jul 4in UTC and inevery zone from UTC-07:00 eastward,
Jul 3west of it. The comment in the new case says exactlythis, and the two equivalences either side of the literal are TZ-free and carry the property alone.
This exposure is pre-existing and out of scope here — measured, not assumed: at the branch base
411a132c0,TZ=Etc/GMT+8 pnpm exec vitest run <the pin file>already givesTests 10 failed | 4 passed (14)without this PR's row. Reported to the PM as an out-of-scopefinding (6 files, 49 literal day-bearing assertions in the family) rather than filed: the session's
REST channel is gated 403 and the MCP pool returned
API rate limit already exceeded, so themandatory de-duplication search could not be run, and filing unchecked is the worse failure.
Verification (all quoted from the runner's own summary, at final HEAD
4aef6b774)Test Files 1 passed (1)/Tests 15 passed (15)packages/core/in fullTest Files 122 passed (122)/Tests 2574 passed (2574)packages/coretype-checktsc --noEmit && tsc -p tsconfig.test.json)tsc -p tsconfig.test.json --listFileshits the pin file 1; the maintsc --noEmitprogram hits it 0 — which is why the script runs bothpackages/coreeslint .✖ 517 problems (0 errors, 517 warnings); 0 of them name this filecheck-changeset-presence✅ 1 source file(s) of 1 released package(s) changed, and this change declares 1 changeset(s): .changeset/pin-relative-out-of-window-precedence-8262.md.+Every one of them has an EMPTY frontmatter — declared as releasing nothing, which is the explicit exemption and a complete answer to this gate.(its first run, before the changeset, was❌ ... adds no changeset— a test-only change under a released package'ssrc/still owes the declaration)check:changeset-no-major✅ No changeset declares a major bump.check:control-bytes✅ check-control-bytes: OK (scanned 6638 tracked text file(s); skipped 85 binary).check:vi-mock-specifiers/check:vi-mock-inherit✅ ... OKcheck-governed-queue-guard --test <the two paths>✅ NOT GOVERNED — 2 path(s) checked against 5 governed surface(s); none matched.(lit control:--test AGENTS.mdfires the governed branch)Every exit code above was captured with
cmd > file 2>&1; EXIT=$?, never through a pipe.Declared narrowing.
turbo ls --affectednames 38 packages, because everything depends on@object-ui/core. The diff is one file underpackages/core/src/**/__tests__/plus a changeset:git grep optionsStyle-7745acrosspackages apps examples scripts e2ereturns zero references(lit control
absoluteFallbackOptionsreturns 2), and@object-ui/core'sfilesis["dist","README.md","CHANGELOG.md","LICENSE"], so no other package can observe it. Everythingoutside
packages/core/is declared to CI.🤖 Generated with Claude Code
https://claude.ai/code/session_01YBWFb5YgMU5dw8p2VKj16S
Generated by Claude Code