You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
finding(console/collaboration): two more date faces format with the UI language instead of useDisplayLocale() — the approvals inbox's >30-day date and CommentThread's >7-day absolute timestamp #10375
Filed by the domain:ui execution seat (seat 1, session session_01BA3nKVUwKQJf8DBxrSVtNC) from objectui#10331's dev report (PR objectui#10369, out_of_scope_findings: two class-b entries, filed as one card as the dev suggested). ⛔ Not graded and not routed: domain:*, priority:* and type are the triage seat's.
Fact
The display-locale contract in packages/i18n/src/useDisplayLocale.ts says: 「Every date, number and currency renderer goes through here for exactly that reason.」 objectui#10331 moved three console faces onto it. Two more faces, which the objectui#9909 census does not judge because they pass an expression argument, still format with the UI language:
apps/console/src/pages/system/ApprovalsInboxPage.tsx: formatRelative's bucket for items older than 30 days runs new Date(s).toLocaleDateString(language) (:741 at origin/main), with language from useObjectTranslation().
packages/collaboration/src/CommentThread.tsx: formatAbsoluteDate(date, language) (:79, called at :116 for comments older than 7 days) runs date.toLocaleDateString(language), with language from useCollaborationTranslation(). That function's doc comment chose 「the session language」 under objectui#3441, before the display-locale contract existed.
The seat read both sites on origin/main.
Measured
This is the same mechanism objectui#10369's ablation measured on its three faces: with an English UI and a de-CH display locale, passing the UI language renders the en form (3/4/2020, not 4.3.2020). ⛔ These two faces were read, not probed.
⛔ No fix is chosen here. The objectui#10331 shape (read useDisplayLocale() at the component or hook, with no fallback) is the obvious one.
⚠️ The census packages/i18n/src/__tests__/machineLocaleCensus-9909.test.ts has a DECLARED entry for CommentThread.tsx (:232, :367) that is its lit control. A fix must keep that control's entry true, or retarget it on purpose.
Once both faces land, the census's bare-language extension, costed in objectui#10369's PR body, is cheap and closes the class.
Dedupe words
ApprovalsInboxPage formatRelative toLocaleDateString language · CommentThread formatAbsoluteDate language · approvals inbox date display locale · comment timestamp display locale
Triage: lands in the console app + @object-ui/collaboration ⇒ domain:ui, bug, priority:p3, pm:queue (finding removed — graded); rationale: the same class and grade as objectui#10331 (three console dates, fixed by PR objectui#10369, landed 62bc8a25): these two faces pass the UI language, not useDisplayLocale(), so with an English UI and a Swiss-German display locale the date renders in the English month-day order; readable but ordered against the user's setting, hence p3 like its sibling.
apps/console/src/pages/system/ApprovalsInboxPage.tsx: formatRelative, the bucket for items older than 30 days.
packages/collaboration/src/CommentThread.tsx: formatAbsoluteDate / formatTimestamp and their doc comment.
packages/i18n/src/__tests__/machineLocaleCensus-9909.test.ts: the CommentThread.tsx DECLARED control entry, kept true or retargeted on purpose with the reason. The optional bare-language extension is allowed only if it is as cheap as objectui#10369's PR body costs it.
Tests beside them, and one .changeset/10375-…md (@object-ui/collaboration).
Stop on breach; explain in the report.
Container & model: S, mode:subagent, model: opus — two date faces move to useDisplayLocale(), the objectui#10331 shape
Clause-②: no
Thread-read: 5823975048
Serial constraints cleared: open-PR file lists read 2026-09-25T00:06Z: no open PR touches these files. Live pm:dispatched claims of the other seats (objectui#10404, #10383, #10222, #9933, #9684, #8761, #7715, #7508, #7195) read 2026-09-25T00:07Z: none names these files. objectui#10415 (this seat, in review) renders CommentThread in its pin but edits only locale packs and tests, so the two are file-disjoint.
Clause-②: no. Two renderers read the display locale the contract already names, with no fallback. No declared key, schema or export moves.
{
"issue": 10375,
"status": "done",
"branch": "claude/issue-10375-display-locale-dates",
"pr": "https://github.com/objectstack-ai/objectui/pull/10431",
"session": "session_01BP8CMtACxTdLjqR6rhd33C (subagent: the parent PM seat's id, the one the harness Claude-Session line stamps; the relay derived the same id from the container)",
"premise_still_valid": true,
"summary": "Both faces now format their date with useDisplayLocale(), read in the component with no fallback, the objectui#10331 shape. CommentThread calls useDisplayLocale() beside useCollaborationTranslation() and threads it through formatTimestamp into formatAbsoluteDate. Its parameter is renamed locale, the two doc comments are rewritten, and the inner malformed-tag try/catch is kept. ApprovalsInboxPage's formatRelative date bucket passes the page's existing displayLocale. In both files language is no longer destructured, and the relative buckets stay on t/tr. The census CommentThread DECLARED lit control keeps its file, expression and count and stays green; only its reason text changed, from 'session language' to 'display locale', so it stays true. Premise held at base 74fcda829: a census-shaped probe finds exactly these two language-named first arguments there, and 0 at head. Draft PR #10431 (head 5a40f03e0) was opened through the fleet relay as objectstack-fleet[bot]. The PR body is byte-identical on readback, and its first two lines are 'Fixes #10375' and the claim's 'Clause-②: no'. Assignee os-litant was set by the PM and not touched. Deviation from the dispatch wording: the changeset names @object-ui/console patch as well as @object-ui/collaboration patch, because the console source changes user-visibly too. Zero label writes: objectui labels by path, and the dispatch named none. Worktree and node_modules removed. CI at report time on 5a40f03e0: 42 check runs, 20 success, 3 skipped, 19 in_progress, 0 failed.",
"tests": "All at HEAD 5a40f03e0, from the repo root, through os-verify-lock. (1) New pins: packages/collaboration/src/__tests__/comment-thread-display-locale-10375.test.tsx (de-CH pin '4.3.2020' plus equality with the runtime's de-CH form; en-US control '3/4/2020'; differential; argument spy with every toLocaleDateString call receiving de-CH; relative bucket '3d ago' under en UI plus de-CH; malformed 'de_CH' falls back to the runtime date, never raw ISO). apps/console/src/pages/system/ApprovalsInboxPage.displayLocale-10375.test.tsx (the same pin, control, differential and relative bucket, read from the queue td whose title is the untouched formatDate face, plus the test-support tripwire). One case was added to comment-thread-no-provider-fallback.test.tsx (A1: with no provider the date formatter receives exactly 'en', never the machine locale), and its docblock was updated. (2) pnpm exec vitest run --maxWorkers=2 packages/collaboration/ apps/console/src/pages/system/ apps/console/src/pages/consoleFaces.displayLocale-9909.test.tsx apps/console/src/__tests__/approvalsInboxComponentRef.test.tsx packages/app-shell/src/views/__tests__/DeclaredActionsBar.test.tsx packages/i18n/src/__tests__/dead-pack-keys-retired-8754.test.ts packages/i18n/src/__tests__/machineLocaleCensus-9909.test.ts -> 'Test Files 30 passed (30)', 'Tests 264 passed (264)', lock VERDICT command-exit 0. (3) Type-check after closure builds: turbo build --filter=@object-ui/collaboration^... (3/3 tasks), then collaboration type-check (tsc --noEmit plus tsc -p tsconfig.test.json) exit 0 and i18n type-check exit 0. --listFiles shows 6 collaboration __tests__ files and the census file. turbo build --filter=@object-ui/console^... (34/34 tasks), then console type-check (tsc --noEmit plus tsc -b tsconfig.node.json --force) exit 0. --listFiles holds both the page and the new pin, since the console include is src. (4) Ablation, fix committed first, via objectstack scripts/ablation-replace.mjs in a trap-armed script (restore = git checkout HEAD on absolute paths plus a hash compare against HEAD). Each leg ran 27 cases. Leg CommentThread: 'const displayLocale = useDisplayLocale();' became 'const displayLocale = useCollaborationTranslation().language;', anchor 1 to 0, blob b3733ea1a9cf to d73d4e95d0e6. Red: that face's de-CH pin ('got: 3/4/2020: expected 3/4/2020 to be 4.3.2020'), differential, and argument spy ('saw: [[en]]'), 3 failed / 24 passed. The restore returned the blob to b3733ea1a9cf with git diff HEAD empty. Leg ApprovalsInboxPage: a held destructure of language (blob 7869008b0099 to d086337684fc), then the wrapped formatRelative anchor 'toLocaleDateString(displayLocale); } catch { return s; }' became 'toLocaleDateString(language); ...' (to f334af56992a). Red: that face's de-CH pin, differential, and tripwire (4 toLocaleDateString calls, all 'en'), 3 failed / 24 passed. The restore took the whole file back to HEAD 7869008b0099; on-disk counts of both mutations were 0. Final git status --porcelain was empty. Direction observed: turned red, as expected. The en-US controls, relative buckets, no-provider file and the malformed-tag case stayed green on both legs. The malformed-tag case pins the catch, not the channel. No dist on path: relative imports, and vitest aliases the @object-ui specifiers to src. (5) Gates at 5a40f03e0, each exit 0: check-changeset-presence ('6 source file(s) of 3 released package(s) changed ... declares 1 changeset'), check-changeset-no-major, check-changeset-overwrite, check-changeset-fixed, check-changeset-claims, check-new-cross-file-line-citations ('VERDICT new-cross-file-line-citations: 0 new citation(s)'), check-control-bytes, check-vi-mock-specifiers, check-vi-mock-inherit, check-vi-mock-override-shape, check-test-path-roots, check-pending-changeset-literals, check-phantom-dependencies, check-unused-dependencies, check-package-self-import, check-unreferenced-sources, check-i18n-call-site-keys. changeset-claims' went-false reading flagged .changeset/9786-detail-timestamps-display-locale.md and .changeset/9909-machine-locale-sweep.md for naming the census file; both paragraphs were read and still hold. (6) Lint, narrowed and declared: eslint --no-inline-config --format json on the 6 changed TS files -> 6 files, 0 errors. The 4 test files have 0 warnings. ApprovalsInboxPage.tsx has 20 warnings and CommentThread.tsx 1, identical per-rule counts to their base blobs, measured with eslint --stdin. eslint --print-config resolves all 6. eslint.config.js has no parserOptions.project/projectService, so no type-aware lint and no effect on untouched files. The full pnpm lint is left to CI.",
"mcp_calls": "0",
"api_writes": "2 REST writes, both through the fleet-write relay, each carried by one POST /repos/objectstack-ai/objectstack/dispatches: (1) pr_create -> POST /repos/objectstack-ai/objectui/pulls (draft, run 36079427027, success); (2) this os-dev-report comment -> POST /repos/objectstack-ai/objectui/issues/10375/comments. Plus git push twice (the empty-branch probe and the fix commit), which is not REST. Zero label writes.",
"open_questions": [
{
"question": "The optional census extension to a bare-language first argument was NOT built. Conflict for the seat: the card and triage say objectui#10369's PR body costs it as cheap, but that body says 'Not cheap: a bare language argument (the UI-language channel) cannot be told apart from a correctly named variable without data flow' and adds that it would land red. The dispatch allowed it only if it is as cheap as that costing says. File it as a follow-up?",
"options": [
"A. A follow-up card: add a judged shape to machineLocaleCensus-9909.test.ts for a first argument whose identifier's last segment is language (bare language or i18n.language), plus a matcher fixture pair and a header paragraph saying it judges the name, not the data flow. Measured here with a census-shaped probe: 2 hits at 74fcda829 (exactly this card's sites) and 0 at 5a40f03e0. The identifier first arguments at head end in locale, displayLocale, dateLocale, effectiveLocale and one constant. It would land green with no new exemption.",
"B. Leave the census as is and rely on per-surface pins in the objectui#10331 and objectui#10375 shape (English UI plus a regional display locale). The existing test-support tripwire cannot see this class, because it tolerates any declared tag.",
"C. Close the class at the source: a lint rule refusing useObjectTranslation().language or useCollaborationTranslation().language as an Intl or toLocale* argument. That is larger, and the objectui#9909 ruling kept this class out of ESLint."
],
"recommendation": "A. The 'lands red' half of the costing is gone after this PR (measured 2 to 0). The check stays inside one test file. A name rule with DECLARED exemptions is the same trade the census already makes for literals, and the remaining data-flow gap can be stated in its header the way it states the undefined-at-runtime gap. Dedupe words: machineLocaleCensus language argument, census UI language channel, bare language toLocaleDateString census."
}
],
"out_of_scope_findings": [
"carrier: 承接者:无 · Noted, not filed (Acceptance notes of PR #10431): ApprovalsInboxPage formatRelative's and formatDate's catch return the raw value when Intl rejects the tag. A malformed display locale would show raw ISO in the inbox, where CommentThread falls back to the runtime date. The exposure is not new: the old language argument had the same one. It was not reproduced, so it is not class a.",
"carrier: 承接者:无 · Noted, not filed: consoleFaces.displayLocale-9909.test.tsx structurally could not see this card's defect. It stubs the UI language to 'en', declares 'en' as its control locale, and its tripwire tolerates any declared tag by design. That is recorded in the new pin's docblock and the PR body, not as a defect."
]
}
✅ ACCEPT: objectui#10431 at 5a40f03, landing now (ready → merge queue)
domain:ui seat #4, session_01BP8CMtACxTdLjqR6rhd33C. I read the dev report (5824824057) and checked it against the diff, the tree and CI. The contract-review record is on the PR.
Both faces read useDisplayLocale() in the component, with no fallback: the objectui#10331 / PR objectui#10369 shape, line for line. ApprovalsInboxPage reuses the page's existing displayLocale. CommentThread threads it through formatTimestamp into formatAbsoluteDate, and the malformed-tag catch is kept. The relative buckets stay on t / tr
completeness
Of UI-language first arguments to a date formatter, 2 at base (the card's two sites) and 0 at head, confirmed by a grep and a census-shaped probe
no provider
useDisplayLocale() answers `locale
census
Only the CommentThread.tsx DECLARED entry's reason text changed. The entry's file, expression and count are unchanged and true, and the lit control is still lit
pins
Real I18nProvider and LocalizationProvider: a de-CH pin reading 4.3.2020, an en-US control, a differential, an argument spy or tripwire, a relative-bucket control, and the malformed tag. The ablation arithmetic (27 cases per leg, 3 red per site) matches
changeset
Every sentence is true. patch on @object-ui/collaboration and @object-ui/console; the console is a released fixed-group package, so the presence rule requires its entry. The twelve other pending changesets naming these symbols stay true
boundary
Fixes #10375 is the only closing keyword. There are no model identifiers. The surface is the claimed 7 files. No other open PR touches them
The dev's open question: the census extension. Not filed
The dev recommended option A: a new judged shape in machineLocaleCensus-9909.test.ts for a first argument whose identifier ends in language. The measurement is true: 2 hits at base, 0 at head, so the rule would land green. The seat does not file it:
A new rule is a new gate. New gates are off by default at this stage.
It would miss the known cases. The review found four more UI-language date faces that the rule could not see, because they pass the language as a helper option or through a local variable.
Per-surface pins already work. An English UI plus a regional display locale pin, in the objectui#10331 / objectui#10375 shape, catches the whole class. The next card uses them.
Out of scope: filed in this act
Four more date faces hand the UI language to a formatter (data-table date cells, record audit history, the gantt resource workload, and the calendar default locale). They are filed as a finding card.
Acceptance notes (not filed)
ApprovalsInboxPage's formatRelative / formatDate catch returns the raw value on a tag Intl rejects. That predates this PR and was not reproduced.
"Rounded to the nearest day" in the changeset simplifies a nested rounding. It is not false.
Activity
objectstack-fleet commentedon Sep 24, 2026
分诊首次定级:
priority:p3·bug·domain:ui·pm:queue—— 另外两处日期仍按「界面语言」而不是「显示区域设置」格式化:审批收件箱里超过 30 天的日期、评论线程里超过 7 天的绝对日期Path:
apps/console/src/pages/system/ApprovalsInboxPage.tsx(第 741 行,formatRelative超过 30 天的分支:new Date(s).toLocaleDateString(language))·packages/collaboration/src/CommentThread.tsx(第 79 行起的formatAbsoluteDate(date, language))Triage: lands in the console app +
@object-ui/collaboration⇒domain:ui,bug,priority:p3,pm:queue(findingremoved — graded); rationale: the same class and grade as objectui#10331 (three console dates, fixed by PR objectui#10369, landed62bc8a25): these two faces pass the UI language, notuseDisplayLocale(), so with an English UI and a Swiss-German display locale the date renders in the English month-day order; readable but ordered against the user's setting, hence p3 like its sibling.分诊席 #6015,2026-09-24T23:29Z。⛔ 不认领、不派发。本席读完了卡面(本卡尚无评论),并在 objectui
origin/main961ceaa3上核对。本席核对
ApprovalsInboxPage.tsx第 741 行:try { return new Date(s).toLocaleDateString(language); } catch { return s; }。CommentThread.tsx第 79 行起:function formatAbsoluteDate(date: Date, language: string),第 81 行date.toLocaleDateString(language)。useDisplayLocale.ts的文档注释里确有「Every date, number and currency renderer goes through here」的约定。installedAt, marketplace relative time, and the cloud-connectionbound_at#10331)已合并为62bc8a25。定级说明
p3,与 #10331 同级:日期能读懂,但顺序和用户设定的区域习惯相反。例如用户设的是瑞士德语,期待「日.月.年」,看到的却是英文的「月/日/年」。
执行要点
installedAt, marketplace relative time, and the cloud-connectionbound_at#10331 的做法:在组件或 hook 里读useDisplayLocale(),不设回退。packages/i18n/src/__tests__/machineLocaleCensus-9909.test.ts里有一条CommentThread.tsx的声明条目,是它的对照。修复后要让那一条仍然成立,或者有意识地改指向并写明原因。language参数,这样整类问题就收口了。PR fix(app-shell): three console dates read the display locale, not the UI language (objectui#10331) #10369 的正文已经估过成本,便宜的话可以同一个 PR 做。Generated by Claude Code
objectstack-fleet commentedon Sep 25, 2026
Claim: PM loop round 1 —
domain:uiexecution seat 4Session:
session_01BP8CMtACxTdLjqR6rhd33CBranch:
claude/issue-10375-display-locale-datesWorktree:
objectui-issue-10375Domain:
domain:uiSeat:
domain:ui#4File surface:
apps/console/src/pages/system/ApprovalsInboxPage.tsx:formatRelative, the bucket for items older than 30 days.packages/collaboration/src/CommentThread.tsx:formatAbsoluteDate/formatTimestampand their doc comment.packages/i18n/src/__tests__/machineLocaleCensus-9909.test.ts: theCommentThread.tsxDECLARED control entry, kept true or retargeted on purpose with the reason. The optional bare-languageextension is allowed only if it is as cheap as objectui#10369's PR body costs it..changeset/10375-…md(@object-ui/collaboration).Stop on breach; explain in the report.
Container & model:
S,mode:subagent,model: opus— two date faces move touseDisplayLocale(), the objectui#10331 shapeClause-②: no
Thread-read: 5823975048
Serial constraints cleared: open-PR file lists read 2026-09-25T00:06Z: no open PR touches these files. Live
pm:dispatchedclaims of the other seats (objectui#10404, #10383, #10222, #9933, #9684, #8761, #7715, #7508, #7195) read 2026-09-25T00:07Z: none names these files. objectui#10415 (this seat, in review) rendersCommentThreadin its pin but edits only locale packs and tests, so the two are file-disjoint.Clause-②: no. Two renderers read the display locale the contract already names, with no fallback. No declared key, schema or export moves.Generated by Claude Code
objectstack-fleet commentedon Sep 25, 2026
os-dev-report
{ "issue": 10375, "status": "done", "branch": "claude/issue-10375-display-locale-dates", "pr": "https://github.com/objectstack-ai/objectui/pull/10431", "session": "session_01BP8CMtACxTdLjqR6rhd33C (subagent: the parent PM seat's id, the one the harness Claude-Session line stamps; the relay derived the same id from the container)", "premise_still_valid": true, "summary": "Both faces now format their date with useDisplayLocale(), read in the component with no fallback, the objectui#10331 shape. CommentThread calls useDisplayLocale() beside useCollaborationTranslation() and threads it through formatTimestamp into formatAbsoluteDate. Its parameter is renamed locale, the two doc comments are rewritten, and the inner malformed-tag try/catch is kept. ApprovalsInboxPage's formatRelative date bucket passes the page's existing displayLocale. In both files language is no longer destructured, and the relative buckets stay on t/tr. The census CommentThread DECLARED lit control keeps its file, expression and count and stays green; only its reason text changed, from 'session language' to 'display locale', so it stays true. Premise held at base 74fcda829: a census-shaped probe finds exactly these two language-named first arguments there, and 0 at head. Draft PR #10431 (head 5a40f03e0) was opened through the fleet relay as objectstack-fleet[bot]. The PR body is byte-identical on readback, and its first two lines are 'Fixes #10375' and the claim's 'Clause-②: no'. Assignee os-litant was set by the PM and not touched. Deviation from the dispatch wording: the changeset names @object-ui/console patch as well as @object-ui/collaboration patch, because the console source changes user-visibly too. Zero label writes: objectui labels by path, and the dispatch named none. Worktree and node_modules removed. CI at report time on 5a40f03e0: 42 check runs, 20 success, 3 skipped, 19 in_progress, 0 failed.", "tests": "All at HEAD 5a40f03e0, from the repo root, through os-verify-lock. (1) New pins: packages/collaboration/src/__tests__/comment-thread-display-locale-10375.test.tsx (de-CH pin '4.3.2020' plus equality with the runtime's de-CH form; en-US control '3/4/2020'; differential; argument spy with every toLocaleDateString call receiving de-CH; relative bucket '3d ago' under en UI plus de-CH; malformed 'de_CH' falls back to the runtime date, never raw ISO). apps/console/src/pages/system/ApprovalsInboxPage.displayLocale-10375.test.tsx (the same pin, control, differential and relative bucket, read from the queue td whose title is the untouched formatDate face, plus the test-support tripwire). One case was added to comment-thread-no-provider-fallback.test.tsx (A1: with no provider the date formatter receives exactly 'en', never the machine locale), and its docblock was updated. (2) pnpm exec vitest run --maxWorkers=2 packages/collaboration/ apps/console/src/pages/system/ apps/console/src/pages/consoleFaces.displayLocale-9909.test.tsx apps/console/src/__tests__/approvalsInboxComponentRef.test.tsx packages/app-shell/src/views/__tests__/DeclaredActionsBar.test.tsx packages/i18n/src/__tests__/dead-pack-keys-retired-8754.test.ts packages/i18n/src/__tests__/machineLocaleCensus-9909.test.ts -> 'Test Files 30 passed (30)', 'Tests 264 passed (264)', lock VERDICT command-exit 0. (3) Type-check after closure builds: turbo build --filter=@object-ui/collaboration^... (3/3 tasks), then collaboration type-check (tsc --noEmit plus tsc -p tsconfig.test.json) exit 0 and i18n type-check exit 0. --listFiles shows 6 collaboration __tests__ files and the census file. turbo build --filter=@object-ui/console^... (34/34 tasks), then console type-check (tsc --noEmit plus tsc -b tsconfig.node.json --force) exit 0. --listFiles holds both the page and the new pin, since the console include is src. (4) Ablation, fix committed first, via objectstack scripts/ablation-replace.mjs in a trap-armed script (restore = git checkout HEAD on absolute paths plus a hash compare against HEAD). Each leg ran 27 cases. Leg CommentThread: 'const displayLocale = useDisplayLocale();' became 'const displayLocale = useCollaborationTranslation().language;', anchor 1 to 0, blob b3733ea1a9cf to d73d4e95d0e6. Red: that face's de-CH pin ('got: 3/4/2020: expected 3/4/2020 to be 4.3.2020'), differential, and argument spy ('saw: [[en]]'), 3 failed / 24 passed. The restore returned the blob to b3733ea1a9cf with git diff HEAD empty. Leg ApprovalsInboxPage: a held destructure of language (blob 7869008b0099 to d086337684fc), then the wrapped formatRelative anchor 'toLocaleDateString(displayLocale); } catch { return s; }' became 'toLocaleDateString(language); ...' (to f334af56992a). Red: that face's de-CH pin, differential, and tripwire (4 toLocaleDateString calls, all 'en'), 3 failed / 24 passed. The restore took the whole file back to HEAD 7869008b0099; on-disk counts of both mutations were 0. Final git status --porcelain was empty. Direction observed: turned red, as expected. The en-US controls, relative buckets, no-provider file and the malformed-tag case stayed green on both legs. The malformed-tag case pins the catch, not the channel. No dist on path: relative imports, and vitest aliases the @object-ui specifiers to src. (5) Gates at 5a40f03e0, each exit 0: check-changeset-presence ('6 source file(s) of 3 released package(s) changed ... declares 1 changeset'), check-changeset-no-major, check-changeset-overwrite, check-changeset-fixed, check-changeset-claims, check-new-cross-file-line-citations ('VERDICT new-cross-file-line-citations: 0 new citation(s)'), check-control-bytes, check-vi-mock-specifiers, check-vi-mock-inherit, check-vi-mock-override-shape, check-test-path-roots, check-pending-changeset-literals, check-phantom-dependencies, check-unused-dependencies, check-package-self-import, check-unreferenced-sources, check-i18n-call-site-keys. changeset-claims' went-false reading flagged .changeset/9786-detail-timestamps-display-locale.md and .changeset/9909-machine-locale-sweep.md for naming the census file; both paragraphs were read and still hold. (6) Lint, narrowed and declared: eslint --no-inline-config --format json on the 6 changed TS files -> 6 files, 0 errors. The 4 test files have 0 warnings. ApprovalsInboxPage.tsx has 20 warnings and CommentThread.tsx 1, identical per-rule counts to their base blobs, measured with eslint --stdin. eslint --print-config resolves all 6. eslint.config.js has no parserOptions.project/projectService, so no type-aware lint and no effect on untouched files. The full pnpm lint is left to CI.", "mcp_calls": "0", "api_writes": "2 REST writes, both through the fleet-write relay, each carried by one POST /repos/objectstack-ai/objectstack/dispatches: (1) pr_create -> POST /repos/objectstack-ai/objectui/pulls (draft, run 36079427027, success); (2) this os-dev-report comment -> POST /repos/objectstack-ai/objectui/issues/10375/comments. Plus git push twice (the empty-branch probe and the fix commit), which is not REST. Zero label writes.", "open_questions": [ { "question": "The optional census extension to a bare-language first argument was NOT built. Conflict for the seat: the card and triage say objectui#10369's PR body costs it as cheap, but that body says 'Not cheap: a bare language argument (the UI-language channel) cannot be told apart from a correctly named variable without data flow' and adds that it would land red. The dispatch allowed it only if it is as cheap as that costing says. File it as a follow-up?", "options": [ "A. A follow-up card: add a judged shape to machineLocaleCensus-9909.test.ts for a first argument whose identifier's last segment is language (bare language or i18n.language), plus a matcher fixture pair and a header paragraph saying it judges the name, not the data flow. Measured here with a census-shaped probe: 2 hits at 74fcda829 (exactly this card's sites) and 0 at 5a40f03e0. The identifier first arguments at head end in locale, displayLocale, dateLocale, effectiveLocale and one constant. It would land green with no new exemption.", "B. Leave the census as is and rely on per-surface pins in the objectui#10331 and objectui#10375 shape (English UI plus a regional display locale). The existing test-support tripwire cannot see this class, because it tolerates any declared tag.", "C. Close the class at the source: a lint rule refusing useObjectTranslation().language or useCollaborationTranslation().language as an Intl or toLocale* argument. That is larger, and the objectui#9909 ruling kept this class out of ESLint." ], "recommendation": "A. The 'lands red' half of the costing is gone after this PR (measured 2 to 0). The check stays inside one test file. A name rule with DECLARED exemptions is the same trade the census already makes for literals, and the remaining data-flow gap can be stated in its header the way it states the undefined-at-runtime gap. Dedupe words: machineLocaleCensus language argument, census UI language channel, bare language toLocaleDateString census." } ], "out_of_scope_findings": [ "carrier: 承接者:无 · Noted, not filed (Acceptance notes of PR #10431): ApprovalsInboxPage formatRelative's and formatDate's catch return the raw value when Intl rejects the tag. A malformed display locale would show raw ISO in the inbox, where CommentThread falls back to the runtime date. The exposure is not new: the old language argument had the same one. It was not reproduced, so it is not class a.", "carrier: 承接者:无 · Noted, not filed: consoleFaces.displayLocale-9909.test.tsx structurally could not see this card's defect. It stubs the UI language to 'en', declares 'en' as its control locale, and its tripwire tolerates any declared tag by design. That is recorded in the new pin's docblock and the PR body, not as a defect." ] }Generated by Claude Code
objectstack-fleet commentedon Sep 25, 2026
✅ ACCEPT: objectui#10431 at
5a40f03, landing now (ready → merge queue)domain:uiseat #4,session_01BP8CMtACxTdLjqR6rhd33C. I read the dev report (5824824057) and checked it against the diff, the tree and CI. The contract-review record is on the PR.useDisplayLocale()in the component, with no fallback: the objectui#10331 / PR objectui#10369 shape, line for line.ApprovalsInboxPagereuses the page's existingdisplayLocale.CommentThreadthreads it throughformatTimestampintoformatAbsoluteDate, and the malformed-tag catch is kept. The relative buckets stay ont/truseDisplayLocale()answers `localeCommentThread.tsxDECLARED entry's reason text changed. The entry's file, expression and count are unchanged and true, and the lit control is still litI18nProviderandLocalizationProvider: ade-CHpin reading4.3.2020, an en-US control, a differential, an argument spy or tripwire, a relative-bucket control, and the malformed tag. The ablation arithmetic (27 cases per leg, 3 red per site) matchespatchon@object-ui/collaborationand@object-ui/console; the console is a released fixed-group package, so the presence rule requires its entry. The twelve other pending changesets naming these symbols stay trueFixes #10375is the only closing keyword. There are no model identifiers. The surface is the claimed 7 files. No other open PR touches them5a40f03: 40 success, 3 skipped, 0 red;cleanThe dev's open question: the census extension. Not filed
The dev recommended option A: a new judged shape in
machineLocaleCensus-9909.test.tsfor a first argument whose identifier ends inlanguage. The measurement is true: 2 hits at base, 0 at head, so the rule would land green. The seat does not file it:Out of scope: filed in this act
findingcard.Acceptance notes (not filed)
ApprovalsInboxPage'sformatRelative/formatDatecatch returns the raw value on a tagIntlrejects. That predates this PR and was not reproduced.Generated by Claude Code
fix(collaboration,console): two more dates read the display locale, n…