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
console: a user with no stored language who picked 中文 on the sign-in page sees English month names in date cells on every load, because the Accept-Language answer outranks the UI language #27625
Filing gate: ① a product defect with a named location and a reproduction. Found by the #27498 dev (card thread on branch claude/project-thread-b2omyd, PR #27624, os-dev-report 6500538340) while reproducing #27498. ⛔ Not a claim; triage sets lane and grade. PR #27624 fixes the language-switch race and does not close this.
Business reason. A Chinese-speaking user whose sys_user.locale was never written (they chose 中文 on the sign-in page, not through the avatar menu) sees every list grid's dates as Nov 18 / Oct 11 under Chinese headers, on every page load, while the UI language is Chinese. Dates read as foreign text in the one place a user scans them most.
Measured (dev's reproduction on examples/app-showcase)
sys_user.locale unset, device/sign-in language zh: GET /api/v1/auth/me/localization answers the Accept-Language rung, and ui/packages/i18n/src/useDisplayLocale.ts (~L64-68) returns localization.locale || language || 'en', so the server's answer outranks the active UI language. The grid's 截止日期 column reads Nov 18 on every load.
Wanted (design call, not decided here)
Which source wins for display formatting when the user never chose a language: the server's request-derived answer, or the UI language the user picked on the sign-in page. Changing useDisplayLocale's precedence touches every date/number renderer; a server-side answer (marking an Accept-Language-derived locale as such) is the other route.
Dedupe
Open domain:ui titles read for locale, language, month, Accept-Language: only #27498 (the switch race, PR #27624). New.
If the measurement shows the header already carries zh and the answer is still en, return it with pm:retriage and the measured request and answer. ⛔ Do not flip the precedence in useDisplayLocale: that touches every renderer.
Claim: PM loop round 1 · 2026-10-29T16:18Z
Session: session_01Utp6CY2n1JmZZKrHgtp9jC (seat; implementation by a card thread, mode:thread)
Account: os-bill
Branch: claude/project-thread-r5i7sq (the card thread's harness push branch, self-reported — the measured platform exception to claude/issue-N-slug)
Worktree: objectstack-issue-27625
Domain: domain:ui
Seat: domain:ui#2
File surface: ui/apps/console/src/languageSeed.ts, ui/apps/console/src/LocalizationFetchProvider.tsx, the module holding the sign-in page's language pick (measured by the dev, named in the report), tests beside, a changeset; ⛔ useDisplayLocale precedence, every server file, and the auth pages #27509 holds (stop on breach; explain in the report)
Container & model: M, mode:thread, model: TIER_DEFAULT (dispatch-gates --tier: no path-derived mandate), effort: high
Clause-②: no (expected; the dev measures from the diff)
Metadata-protocol: none (expected; the dev measures from the diff)
Responsibility: the console's sign-in language pick (not reaching <html lang> / the localization read's Accept-Language) | the server's rung order and useDisplayLocale's precedence are fixed inputs (triage 6501838569) | every user with no stored language who picks one on the sign-in page, today
Thread-read: 6501838569
Premise: holds as filed by the seat (#27498 dev's reproduction); step 1 of the order re-measures the request header and answer, and returns the card for pm:retriage if the header already carries the picked language
Serial constraints cleared: #27498 (PR #27624, same LocalizationFetchProvider.tsx) merged; ui/apps/console/src/pages/auth/{LoginPage,RegisterPage}.tsx and app-shell/src/console/auth/** excluded while #27509 is in flight; seat 4 handed this card to seat 2
Dispatch order: /mnt/project-files/ui-seat2/dispatch-27625.md in the Claude Code project (not on GitHub); its ruling section quotes the triage text above verbatim.
{
"issue": 27625,
"status": "done",
"branch": "claude/project-thread-r5i7sq",
"pr": "https://github.com/objectstack-ai/objectstack/pull/27680",
"head": "42e6d4b6",
"session": "session_01Utp6CXAd1Uo5DCp8mUzmWj (card thread; seat session_01Utp6CY2n1JmZZKrHgtp9jC)",
"premise_still_valid": true,
"summary": "Defect holds as filed; two mechanism assumptions of the order are falsified. Step-1 measurement on app-showcase (main 144702ca, browser en-US, sys_user.locale unset): the html lang attribute is zh after the sign-in pick and after sign-in, but GET /api/v1/auth/me/localization carries Accept-Language en-US and answers locale en-US; dates Oct 11 / Nov 18 on both loads. Not the retriage case (header not zh). Cause: LocalizationFetchProvider reads through sharedGetJson's bare fetch, which never gets createAuthenticatedFetch's html-lang Accept-Language stamp. Fix (seat agreed the route 16:31Z): when the device holds an explicit language choice (readStoredLanguage), the read states the active UI language as Accept-Language, and statedLanguage is an effect dependency so a change reads again; with no choice nothing is stated, keeping the first-visit share with seedTenantLanguage (objectui#5544). After the fix the same run states zh, answers zh, cells 10月11日 / 11月18日. No server file, no useDisplayLocale change, no new key; languageSeed.ts and the pick's module (app-shell LocaleSwitcher via useLanguageSelection, signed out a bare changeLanguage) unchanged.",
"tests": "head 861694dd: pnpm --dir ui exec vitest run --reporter=verbose apps/console/src/LocalizationFetchProvider.test.tsx apps/console/src/__tests__/localizationBootDedup.test.tsx apps/console/src/languageSeed.test.ts -> Test Files 3 passed (3), Tests 33 passed (33); 4 new cases under 'states the device's chosen language (objectstack#27625)', the 4 #27498 re-read cases green. Ablation via scripts/ablation-replace.mjs (fix committed first): statedLanguage gate -> && !'ABLATED_27625' (anchor 1 -> 0, blob 5147c4a0 -> a88b06c9): Tests 3 failed | 19 passed (22), the no-choice control stays green; restored, blob == HEAD, git diff HEAD empty. No dist involved (console suite resolves src). Head 42e6d4b6: pnpm --dir ui exec vitest run apps/console/src/ -> Test Files 262 passed (262), Tests 2606 passed (2606). Live: stored rung read with explicit headers: column unset + zh -> zh; column ja-JP + zh -> ja-JP; column ja-JP + en-US -> ja-JP; reset + zh -> zh.",
"gates": "head 42e6d4b6 (after merging origin/main once): node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack, 3 paths vs merge base b761968d9: 33 derived, every one exit 0 (incl. check-sdui-manifest.mjs and --self-test, the changeset gates, pnpm --dir ui exec vitest run scripts/ -> Tests 4902 passed | 2 skipped). --ran reconciliation: 33 derived, 33 run, 0 NOT-MEASURED, 0 UNRUN. Outside the derivation: pnpm check:changeset-fixed exit 0; pnpm --filter @object-ui/console run type-check exit 0 (after pnpm --filter '@object-ui/console^...' build exit 0); eslint --no-inline-config on the 2 touched files exit 0. PR check-runs: in_progress at report time (not waited on, per contract); Type Check UI / workspace type-check lanes, wide-population families, artifact rosters and pnpm lint are CI's.",
"dogfood_battery": "n/a — no ! in the PR title and no (narrowing) arm",
"mcp_calls": "0 — no MCP GitHub calls (GitHub reads were REST via gh api; one claude-code-remote get_session to read this session's id)",
"api_writes": "2 — POST /repos/objectstack-ai/objectstack/dispatches (relay pr_create -> #27680, read-back 9399 bytes identical, assignees none), POST /repos/objectstack-ai/objectstack/issues/27625/comments (this report, post-stamped); plus 3 git pushes to the branch (5c262c6a, 11288d79, 42e6d4b6)",
"line_budget": "3 files, +152 / -4 (changeset +12, provider +36/-3, test +104/-1)",
"files_changed": [
".changeset/27625-localization-read-states-chosen-language.md",
"ui/apps/console/src/LocalizationFetchProvider.tsx",
"ui/apps/console/src/LocalizationFetchProvider.test.tsx"
],
"deviations": [
"The order's file surface named languageSeed.ts and the sign-in pick's module; measurement showed neither needs a change, so the diff is LocalizationFetchProvider.tsx + its test + a changeset. Falsified assumptions: (1) the pick does reach the html lang attribute; (2) the triage line 'the console's Accept-Language already follows' that attribute does not hold for this read. Seat agreed the route before the fix.",
"No assignee and no reviewer on the PR; the harness's post-PR assign/review step skipped per the maintainer's rule. No PR subscription taken, per the os-dev contract."
],
"open_questions": [],
"out_of_scope_findings": [
"carrier: none · noted in PR Acceptance notes: a language picked on the sign-in page is still not written to sys_user.locale at sign-in (signed-out globe is the bare switch by design in useLanguageSelection); with this fix the device's dates follow the pick, other devices of the same user still get their own header"
]
}
Activity
objectstack-fleet commentedon Oct 29, 2026
triage#1 · os-zhuang · session_01AavokzJ5DndAwitDXvKy4U
Path: 客户的语言 | none | P②
Triage: p2 ·
domain:ui·area:i18n· 2026-10-29T16:04Z⛔ Not a claim.
/auth/me/localizationrung order stays: storedsys_user.locale, then the request'sAccept-Language, then the default.useDisplayLocale's precedence stays: a stored locale still outranks the UI language.Accept-Languagealready follows<html lang>(languageSeed.ts). So the fix is that the sign-in pick reaches<html lang>, and that the localization read re-runs once it does, the same way zh-CN: list grid date cells render English month abbreviations ("Oct 11", "Nov 1") while the same record's page renders 2026年10月11日 #27498 re-reads after the column write.zhand the answer is stillen, return it withpm:retriageand the measured request and answer. ⛔ Do not flip the precedence inuseDisplayLocale: that touches every renderer.bug,pm:queue.Generated by Claude Code
objectstack-fleet commentedon Oct 29, 2026
domain:ui#2 · os-bill · session_01Utp6CY2n1JmZZKrHgtp9jC
Claim: PM loop round 1 · 2026-10-29T16:18Z
Session:
session_01Utp6CY2n1JmZZKrHgtp9jC(seat; implementation by a card thread,mode:thread)Account:
os-billBranch:
claude/project-thread-r5i7sq(the card thread's harness push branch, self-reported — the measured platform exception toclaude/issue-N-slug)Worktree:
objectstack-issue-27625Domain:
domain:uiSeat:
domain:ui#2File surface:
ui/apps/console/src/languageSeed.ts,ui/apps/console/src/LocalizationFetchProvider.tsx, the module holding the sign-in page's language pick (measured by the dev, named in the report), tests beside, a changeset; ⛔useDisplayLocaleprecedence, every server file, and the auth pages #27509 holds (stop on breach; explain in the report)Container & model:
M,mode:thread,model: TIER_DEFAULT(dispatch-gates --tier: no path-derived mandate),effort: highClause-②: no (expected; the dev measures from the diff)
Metadata-protocol: none (expected; the dev measures from the diff)
Responsibility: the console's sign-in language pick (not reaching
<html lang>/ the localization read'sAccept-Language) | the server's rung order anduseDisplayLocale's precedence are fixed inputs (triage 6501838569) | every user with no stored language who picks one on the sign-in page, todayThread-read: 6501838569
Premise: holds as filed by the seat (#27498 dev's reproduction); step 1 of the order re-measures the request header and answer, and returns the card for
pm:retriageif the header already carries the picked languageSerial constraints cleared: #27498 (PR #27624, same
LocalizationFetchProvider.tsx) merged;ui/apps/console/src/pages/auth/{LoginPage,RegisterPage}.tsxandapp-shell/src/console/auth/**excluded while #27509 is in flight; seat 4 handed this card to seat 2Dispatch order:
/mnt/project-files/ui-seat2/dispatch-27625.mdin the Claude Code project (not on GitHub); its ruling section quotes the triage text above verbatim.Generated by Claude Code
test(console): pin the localization read's stated language (#27625)
chore(changeset): console localization read states the chosen language (
objectstack-fleet commentedon Oct 29, 2026
domain:ui#2 · os-bill · session_01Utp6CY2n1JmZZKrHgtp9jC
os-dev-report
{ "issue": 27625, "status": "done", "branch": "claude/project-thread-r5i7sq", "pr": "https://github.com/objectstack-ai/objectstack/pull/27680", "head": "42e6d4b6", "session": "session_01Utp6CXAd1Uo5DCp8mUzmWj (card thread; seat session_01Utp6CY2n1JmZZKrHgtp9jC)", "premise_still_valid": true, "summary": "Defect holds as filed; two mechanism assumptions of the order are falsified. Step-1 measurement on app-showcase (main 144702ca, browser en-US, sys_user.locale unset): the html lang attribute is zh after the sign-in pick and after sign-in, but GET /api/v1/auth/me/localization carries Accept-Language en-US and answers locale en-US; dates Oct 11 / Nov 18 on both loads. Not the retriage case (header not zh). Cause: LocalizationFetchProvider reads through sharedGetJson's bare fetch, which never gets createAuthenticatedFetch's html-lang Accept-Language stamp. Fix (seat agreed the route 16:31Z): when the device holds an explicit language choice (readStoredLanguage), the read states the active UI language as Accept-Language, and statedLanguage is an effect dependency so a change reads again; with no choice nothing is stated, keeping the first-visit share with seedTenantLanguage (objectui#5544). After the fix the same run states zh, answers zh, cells 10月11日 / 11月18日. No server file, no useDisplayLocale change, no new key; languageSeed.ts and the pick's module (app-shell LocaleSwitcher via useLanguageSelection, signed out a bare changeLanguage) unchanged.", "tests": "head 861694dd: pnpm --dir ui exec vitest run --reporter=verbose apps/console/src/LocalizationFetchProvider.test.tsx apps/console/src/__tests__/localizationBootDedup.test.tsx apps/console/src/languageSeed.test.ts -> Test Files 3 passed (3), Tests 33 passed (33); 4 new cases under 'states the device's chosen language (objectstack#27625)', the 4 #27498 re-read cases green. Ablation via scripts/ablation-replace.mjs (fix committed first): statedLanguage gate -> && !'ABLATED_27625' (anchor 1 -> 0, blob 5147c4a0 -> a88b06c9): Tests 3 failed | 19 passed (22), the no-choice control stays green; restored, blob == HEAD, git diff HEAD empty. No dist involved (console suite resolves src). Head 42e6d4b6: pnpm --dir ui exec vitest run apps/console/src/ -> Test Files 262 passed (262), Tests 2606 passed (2606). Live: stored rung read with explicit headers: column unset + zh -> zh; column ja-JP + zh -> ja-JP; column ja-JP + en-US -> ja-JP; reset + zh -> zh.", "gates": "head 42e6d4b6 (after merging origin/main once): node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack, 3 paths vs merge base b761968d9: 33 derived, every one exit 0 (incl. check-sdui-manifest.mjs and --self-test, the changeset gates, pnpm --dir ui exec vitest run scripts/ -> Tests 4902 passed | 2 skipped). --ran reconciliation: 33 derived, 33 run, 0 NOT-MEASURED, 0 UNRUN. Outside the derivation: pnpm check:changeset-fixed exit 0; pnpm --filter @object-ui/console run type-check exit 0 (after pnpm --filter '@object-ui/console^...' build exit 0); eslint --no-inline-config on the 2 touched files exit 0. PR check-runs: in_progress at report time (not waited on, per contract); Type Check UI / workspace type-check lanes, wide-population families, artifact rosters and pnpm lint are CI's.", "dogfood_battery": "n/a — no ! in the PR title and no (narrowing) arm", "mcp_calls": "0 — no MCP GitHub calls (GitHub reads were REST via gh api; one claude-code-remote get_session to read this session's id)", "api_writes": "2 — POST /repos/objectstack-ai/objectstack/dispatches (relay pr_create -> #27680, read-back 9399 bytes identical, assignees none), POST /repos/objectstack-ai/objectstack/issues/27625/comments (this report, post-stamped); plus 3 git pushes to the branch (5c262c6a, 11288d79, 42e6d4b6)", "line_budget": "3 files, +152 / -4 (changeset +12, provider +36/-3, test +104/-1)", "files_changed": [ ".changeset/27625-localization-read-states-chosen-language.md", "ui/apps/console/src/LocalizationFetchProvider.tsx", "ui/apps/console/src/LocalizationFetchProvider.test.tsx" ], "deviations": [ "The order's file surface named languageSeed.ts and the sign-in pick's module; measurement showed neither needs a change, so the diff is LocalizationFetchProvider.tsx + its test + a changeset. Falsified assumptions: (1) the pick does reach the html lang attribute; (2) the triage line 'the console's Accept-Language already follows' that attribute does not hold for this read. Seat agreed the route before the fix.", "No assignee and no reviewer on the PR; the harness's post-PR assign/review step skipped per the maintainer's rule. No PR subscription taken, per the os-dev contract." ], "open_questions": [], "out_of_scope_findings": [ "carrier: none · noted in PR Acceptance notes: a language picked on the sign-in page is still not written to sys_user.locale at sign-in (signed-out globe is the bare switch by design in useLanguageSelection); with this fix the device's dates follow the pick, other devices of the same user still get their own header" ] }Generated by Claude Code
objectstack-fleet commentedon Oct 29, 2026
domain:ui#2 · os-bill · session_01Utp6CY2n1JmZZKrHgtp9jC
ACCEPT → PR #27680 comment 6504196682 (head
42e6d4b6); contract review not owed (Clause-②: no,Metadata-protocol: none); landing through the merge queue.Generated by Claude Code
objectstack-fleet commentedon Oct 29, 2026
domain:ui#2 · os-bill · session_01Utp6CY2n1JmZZKrHgtp9jC
Landed · 2026-10-29T18:50Z
6cf3e0b1161ec6a7492f520693d176c6db02f7fbcompletedby the PR'sFixeslineState:
pm:dispatchedremoved; the assignee stays as the record of who carried it.Generated by Claude Code