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: the sign-in page renders from the built-in language packs, and the application's translations load after sign-in (the companion of objectstack-ai/objectstack#22432) #12034
Filing gate: ③ a maintainer-directed task. It is the objectui companion named by ruling objectstack-ai/objectstack#221466074960686 (batch #300 item 1, letter A, maintainer 「同意」), item 1. Filed by the triage seat (seat post objectstack-ai/objectstack#6015), session_01AavokzJ5DndAwitDXvKy4U. ⛔ Not a claim.
Why
objectstack-ai/objectstack#22432 gives the framework's /i18n domain the anonymous refusal every other dispatcher domain has (401). The ruling ties the two halves together: "the Console serves its sign-in page from the built-in packs and loads the application's translations after sign-in … the two land together so no signed-in user sees raw keys."
The director's reading recorded in the ruling (objectui main8f8f760fa4)
apps/console/src/main.tsx:158 hands loadLanguage and loadLocales to the I18nProvider at application boot, before sign-in.
loadLanguage.ts:19 and loadLocales.ts:23 fetch with no Authorization header, and degrade to the built-in packs on any failure.
What this card does
Measure first: does the Console re-fetch the application's translations once signed in today? Size the change from that reading.
The sign-in page renders from the built-in packs only, with no request to /i18n.
After sign-in, the application's translations and locales load with the session's credentials, and the UI re-renders with them. Mind objectui#10382: a no-op re-render is a known trap here.
⛔ No signed-in user ever sees raw keys. That includes after a reload, and on the first render after sign-in.
Pins
Anonymous, on the sign-in page: no /i18n request is made, and the page renders translated from the built-in packs.
Signed in: the application's labels are served from the authenticated /i18n reads.
Against a framework whose /i18n answers 401 to an anonymous caller (#22432's head): the whole sign-in → app path shows no raw key.
Cloud pins objectui too. Its pin must carry this change no later than its framework pin carries #22432. That is a row on objectstack-ai/cloud#2709 at landing.
Dedupe: MCP search_issues on objectui, open and closed: 「console sign-in page built-in language packs load application translations after sign-in i18n anonymous loadLanguage」 gave 7 hits, none this. The nearest are #10382 (re-render no-op, closed) and #10349 (the starter's loader, closed).
Claim: PM loop round 16
Session: session_01MgfduSkFrfM3eorB3UGfAU
Account: os-bill
Branch: claude/issue-12034-console-i18n-after-signin
Worktree: objectui-issue-12034
Domain: domain:ui
Seat: domain:ui#2
Scope of this claim: the card's four steps, as filed. Step 1 is a measurement and sizes the rest:
Measure whether the Console re-fetches the application's translations once signed in today.
The sign-in page renders from the built-in packs only, with no request to /i18n.
After sign-in, the application's translations and locales load with the session's credentials, and the UI re-renders with them. The no-op re-render trap of objectui#10382 is checked explicitly.
No signed-in user sees a raw key, including after a reload and on the first render after sign-in.
File surface (as read on main049012b; the dev re-reads it):
apps/console/src/main.tsx, the I18nProvider mount;
apps/console/src/loadLanguage.ts and apps/console/src/loadLocales.ts;
the Console's session or auth state that the post-sign-in load hangs on. The dev names that file before the edit;
the tests beside them, plus one pin test for the card's three pins;
the docs page that describes the Console's translation loading, if one exists. The dev names it or reports that there is none;
any new published prop or export on the I18nProvider or on packages/i18n. If the post-sign-in load cannot be built from the provider's existing API, the dev stops and reports it, and the seat routes it as Clause-②;
any new packages/i18n key;
examples/console-starter: the dev measures its loader and reports. It is not edited here, because the card names the Console.
First-load bytes: main.tsx is in the eager closure. The dev measures the delta against the ceiling of 3,281,467 B and stops before the PR above +1,024 B gzip.
Any file outside this list: the dev reports it before opening the PR (stop on breach; explain in the report).
Container & model: S, mode:subagent, model: opus (dispatch-gates --tier --repo objectstack-ai/objectui over these paths: no path-derived mandate; default tier)
Clause-②: no
Responsibility: objectui Console: the sign-in page fetches /i18n anonymously, and nothing re-loads the application's translations with the session's credentials | the Console's I18nProvider loaders and its session state already on main | every Console user at sign-in, once objectstack-ai/objectstack#22432 refuses an anonymous /i18n read
Thread-read: none
Serial constraints cleared: no open objectui PR and no in-flight claim touches apps/console/src/main.tsx, loadLanguage.ts or loadLocales.ts (read 2026-10-09T07:29Z).
Order: this card lands first. objectstack-ai/objectstack#22432 is Blocked-by: this card, and moves the framework's Console pin past this card's merge (card body).
Why Clause-②: no: the Console is an application, not a published package. Moving its translation load from boot to after sign-in changes no contract and no published prop. New provider props are excluded above.
{
"issue": 12034,
"status": "done",
"branch": "claude/issue-12034-console-i18n-after-signin",
"pr": "#12042",
"session": "session_01MgfduSkFrfM3eorB3UGfAU",
"head": "27caa7d0b",
"premise_still_valid": true,
"summary": "The console's two /i18n loaders (loadLanguage, loadLocales) now wait for this page load's session answer, published by the console AuthProvider's existing onAuthStateChange prop into a new console module (apps/console/src/i18nSession.ts). Signed out they send no request (the sign-in page renders from the built-in packs); signed in they read through withSettleSignal(createAuthenticatedFetch()), the data adapter's own request path (bearer, X-Tenant-ID, Accept-Language). No new prop, export or key on I18nProvider or packages/i18n. Premise partly corrected by measurement: the console already re-reads /i18n after sign-in, because every console sign-in exits by full-page navigation, but never with the bearer; and against the head of objectstack-ai/objectstack#22432, main shows signed-in users the untranslated authored literal, not raw keys.",
"hypotheses": {
"H1": "partly falsified. main blobs vs a fake framework refusing anonymous /i18n (bearer-only): sign-in page load made 2 reads (translations/zh, locales), no Authorization, both 401; the post-sign-in page load (LoginPage exits via window.location.assign, pinned by authExitBasename.test.tsx) made 2 more reads, no Authorization, both 401; heading stayed 'Lead'. Default credentials same-origin: on a same-origin cookie deployment the post-sign-in read would carry the cookie and be served; the bearer was never sent.",
"H2": "partly falsified. head: signed-in page load reads wait for AuthProvider's first answer (one get-session round trip), then carry Bearer, 200. 'First render already has the app labels' holds on neither main nor head: I18nProvider never holds first render for its loader; pin 2 shows Lead then the translation on one mounted heading.",
"H3": "holds with no re-run: existing loadLanguage/loadLocales props unchanged; the loader Promise settles on the session answer and the provider's own non-silent addResourceBundle (bindI18nStore 'added') re-renders. No key remount, no same-language changeLanguage (it would persist an explicit language choice). In-place sign-in is not re-run; the provider has no re-run hook (loadedAppLangs, askedForLocales guards).",
"H4": "holds by falling back, not waiting: sign-in page from the built-in zh pack; first signed-in render = built-in strings + authored literal; MutationObserver over every frame of sign-in to app: 0 raw keys (control catches a raw key). main also showed 0 raw keys: app-bundle readers fall back to the authored literal, and spec I18nLabel refuses the keyed {key, defaultValue} form (key?: never). Built-in call-site key coverage: check:i18n-keys green.",
"H5": "neutral: eagerGzipBytes base 049012b = 3,238,404 B, head 27caa7d = 3,238,537 B, delta +133 B gzip; ceiling 3,281,467 B. check:eager-closure: 'Console eager closure is 3162.6 KB gzipped across 289 of 2474 chunks (budget: 3204.6 KB, headroom: 41.9 KB)'."
},
"starter_measurement": "examples/console-starter (not edited): loader is a bare fetch, no loadLocales, and DefaultLoginPage signs in IN PLACE (navigate('/')). Probe with the starter's real loader vs the 401 framework: before sign-in 1 read, no Authorization, 401; after in-place sign-in 0 reads; heading stayed 'Lead' for the session. Once objectstack-ai/objectstack#22432 lands, starter users see untranslated app labels after sign-in until reload, on every deployment (the pre-sign-in read is anonymous everywhere and the provider never asks again); after reload same-origin cookie is served, bearer-only 401 again. The console's gate is not a drop-in there: in-place sign-in needs the page-load call to wait for a sign-in.",
"tests": "All at head 27caa7d (git rev-parse --short HEAD after the last commit). (1) pnpm exec vitest run over 40 files (3 touched/new test files; 31 apps/console suites mounting I18nProvider, LoginPage or App; 7 suites reading main.tsx/App.tsx source: bootSplash, insecure-origin-crypto.placement, faviconAfterNavigation, tabTitleAfterNavigation, consoleToasterAnchor.ratchet-7482, auth-namespace-3546, runtimeConfigBootDedup; column-identity.ratchet; one-authority-per-exported-name-6273): 'Test Files 40 passed (40)', 'Tests 290 passed (290)', lock VERDICT command-exit 0. (2) reverse leg: loadLanguage.ts, loadLocales.ts, App.tsx, main.tsx swapped for main's blobs (hash == 049012b blob each): pins + loader tests 'Tests 7 failed | 13 passed (20)' (red: pins 1,2,3 + 4 new loader session-rule tests; green: control + pre-existing loader tests); restore via git checkout HEAD, each hash == HEAD blob, git diff HEAD = 0 bytes. (3) wire ablation (only onAuthStateChange={publishAuthState} removed from App.tsx; anchor count 1 to 0): 'Tests 2 failed | 2 passed (4)' (pins 2,3 red; pin 1 + control green as expected); restore proven by hash, git diff HEAD = 0 bytes. All mutation scripts carried trap restore EXIT INT TERM.",
"gates": [
"pnpm --filter @object-ui/console type-check (closure built first: turbo run build --filter=@object-ui/console^... --concurrency=2, VERDICT command-exit 0): echoed 'tsc --noEmit && tsc -b tsconfig.node.json --force', VERDICT command-exit 0; --listFiles includes the 3 test files",
"pnpm exec eslint (8 touched files, --format json): files 8, errors 0, warnings 0, exit 0",
"node scripts/check-changeset-presence.mjs: '8 source file(s) of 1 released package(s) changed, and this change declares 1 changeset(s)', exit 0",
"node scripts/check-changeset-no-major.mjs: 'No changeset declares a major bump', exit 0",
"pnpm check:new-line-citations: 'VERDICT new-cross-file-line-citations: 0 new citation(s), enforcement report-only', then an arrow and 'exit 0' (arrow spelled out for the body sanitizer)",
"pnpm check:control-bytes: 'check-control-bytes: OK (scanned 8189 tracked text file(s); skipped 85 binary)', exit 0",
"pnpm check:i18n-keys: 'Every in-scope call-site key resolves against the en pack (3311 keys) ...', exit 0",
"pnpm check:vi-mock-specifiers / vi-mock-inherit / vi-mock-override-shape: OK, exit 0 each",
"pnpm check:test-path-roots: OK, exit 0",
"pnpm check:changeset-claims: 'No pending changeset names a file this change touches', exit 0",
"pnpm check:pending-changeset-literals: 'No test source names a pending changeset', exit 0",
"pnpm check:unreferenced-sources: 'OK Every shipped source file in every covered package is reachable', exit 0",
"pnpm check:phantom-deps: 'Every in-scope import is declared by the package that publishes it', exit 0",
"pnpm check:eager-closure: 'Console eager closure is 3162.6 KB gzipped across 289 of 2474 chunks (budget: 3204.6 KB, headroom: 41.9 KB)', exit 0",
"node scripts/check-governed-queue-guard.mjs --test (9 paths): 'NOT GOVERNED'",
"NOT MEASURED locally, declared to CI: repo-wide pnpm lint and full pnpm test. docs:check-links and check:spec-symbols not applicable (content/docs untouched)."
],
"eager_closure": {
"base_049012bf0": 3238404,
"head_27caa7d0b": 3238537,
"delta_gzip_bytes": 133,
"ceiling": 3281467,
"ci_budget_bot_reading": "NOT MEASURED: reported after CI by the seat"
},
"files_changed": [
"apps/console/src/i18nSession.ts (new: the session state the post-sign-in load hangs on)",
"apps/console/src/App.tsx (AuthProvider onAuthStateChange={publishAuthState})",
"apps/console/src/loadLanguage.ts",
"apps/console/src/loadLocales.ts",
"apps/console/src/main.tsx (comment only)",
"apps/console/src/loadLanguage.test.tsx",
"apps/console/src/loadLocales.test.ts",
"apps/console/src/tests/i18nAfterSignIn-12034.test.tsx (the card's three pins + a control)",
".changeset/12034-console-i18n-after-signin.md (@object-ui/console: patch)"
],
"docs": "none: no content/docs page describes the console's translation loading; guide/console.md and guide/deployment.md only say the i18n endpoints hang off VITE_SERVER_URL, still true. No docs edit.",
"deviations": [
"The session-state file was named in the PR body and this report, not before the edit: App.tsx (the console's AuthProvider mount) plus a new console module apps/console/src/i18nSession.ts, read as the claim's third bullet.",
"Claim says the Console is 'an application, not a published package'. Measured: @object-ui/console is published (publishConfig.access public, files dist) and in the changesets fixed group; AGENTS.md section 9 Housekeeping requires a changeset for its src, so a patch changeset ships. Clause-2: no still holds (no export, prop or contract change).",
"Commit trailers follow objectui AGENTS.md's model-free pair (Claude-Session + 'Co-authored-by: Claude') instead of the harness reminder's model-named trailer; PR footer uses the agent definition's session-URL form instead of the harness's form.",
"Two temporary probe test files (one in apps/console, one in examples/console-starter) were created, run and deleted, never committed; a detached base worktree was created for the base build and removed.",
"Zero label writes: objectui path labels (apps, tests) were the labeler's; the dispatch named none. Only the PR assignee was written."
],
"mcp_calls": "0",
"api_writes": "3 REST writes through the fleet-write relay (each one POST /repos/objectstack-ai/objectstack/dispatches): pr_create (draft PR #12042, read-back identical 11948 bytes), label-write assign os-bill on PR #12042 (read-back MATCHES), and this os-dev-report comment on #12034. Plus 4 git pushes of the branch (empty-branch probe, then 3 commits' pushes), not REST.",
"open_questions": [],
"out_of_scope_findings": [
"class: a · reach: public door, the console-starter's sign-in (app-shell DefaultLoginPage signs in in place with navigate('/')) against the head of objectstack-ai/objectstack#22432: the app labels stay untranslated for the whole session after sign-in; measured by probe (1 anonymous 401 read before sign-in, 0 reads after, heading 'Lead'). Contingent on objectstack-ai/objectstack#22432 landing; the dispatch asked for this measurement, not an edit. Any host pairing app-shell's DefaultLoginPage with an I18nProvider loader has the same shape, and I18nProvider has no re-run hook after an in-place sign-in, so a fix may need a provider API (Clause-2 territory). · dedupe words: console-starter, in-place sign-in, loadLanguage, i18n 401, DefaultLoginPage",
"carrier: the seat routing objectstack-ai/objectstack#22432 · noted, not filed: if objectstack-ai/objectstack#22432 should also wait on a starter companion, that ordering is the seat's call"
]
}
Implemented-by: os-dev subagent of session_01MgfduSkFrfM3eorB3UGfAU, branch claude/issue-12034-console-i18n-after-signin, head 27caa7d.
Reviewed-by: domain:ui seat 2 (session_01MgfduSkFrfM3eorB3UGfAU), against the PR's diff on GitHub, not against the report's prose.
Built:
apps/console/src/i18nSession.ts (new) holds the console AuthProvider's answer for the page load. App.tsx feeds it through that provider's existing onAuthStateChange prop.
loadLanguage and loadLocales wait for that answer:
signed out, they send no request and answer {} / [], so the sign-in page renders from the built-in packs;
signed in, they read through withSettleSignal(createAuthenticatedFetch()), the data adapter's own request path (bearer, X-Tenant-ID, Accept-Language). No token is lifted from storage, as the claim required.
I18nProvider is used through its existing props. No published prop, export or packages/i18n key is added, so Clause-②: no holds.
The card's premise, corrected by measurement (accepted):
The Console already re-reads /i18n after sign-in, because every console sign-in exits by a full-page navigation (window.location.assign, pinned by authExitBasename.test.tsx). What it never did was send the bearer.
The first render after sign-in shows built-in strings plus the authored literal, then the translation. It never shows a raw key: a MutationObserver over every frame from sign-in to app records zero, and its control catches a key drawn raw.
the new session module and a pin file with the card's three pins plus a control;
one changeset, @object-ui/console: patch.
The session module was named in the report rather than before the edit; the claim's third bullet allowed it.
Changeset: the claim called the Console an application. Measured, @object-ui/console is published and in the fixed group, so AGENTS.md §9 asks for a changeset. Accepted.
Reverse legs:
With main's blobs, 7 of 20 tests turn red (pins 1–3 and the four new loader-session tests).
Removing only the onAuthStateChange wire turns pins 2 and 3 red.
Each was restored to blob == HEAD.
Evidence:
40 files and 290 tests pass, both repo-wide ratchets included.
The Console type-check passes, and eslint shows 0 warnings.
check:i18n-keys, check:phantom-deps, check:unreferenced-sources, both changeset checks and check:eager-closure pass.
Docs: no content/docs page describes the Console's translation loading. guide/console.md and guide/deployment.md only say the endpoints hang off VITE_SERVER_URL, which stays true.
First-load bytes: +133 B gzip (3,238,404 → 3,238,537 B), with 41.9 KB of headroom. The seat's sum of accepted, unlanded deltas is +133 B: PR objectui#12040 is +0 B, and PR objectui#12036 is not accepted.
CI:27caa7d is running. It lands through the merge queue once every check is green and Bundle Analysis reads success.
Order: this card lands first. objectstack-ai/objectstack#22432 is pm:blocked with Blocked-by: this card, and its own PR moves the framework's Console pin past this merge.
Noted for objectstack-ai/objectstack#22432, not this card:examples/console-starter signs in in place, so once #22432 lands its users see untranslated application labels until they reload. That pointer is carried on #22432 itself.
Activity
objectstack-fleet commentedon Oct 9, 2026
Claim: PM loop round 16
Session:
session_01MgfduSkFrfM3eorB3UGfAUAccount:
os-billBranch:
claude/issue-12034-console-i18n-after-signinWorktree:
objectui-issue-12034Domain:
domain:uiSeat:
domain:ui#2Scope of this claim: the card's four steps, as filed. Step 1 is a measurement and sizes the rest:
/i18n.File surface (as read on
main049012b; the dev re-reads it):apps/console/src/main.tsx, theI18nProvidermount;apps/console/src/loadLanguage.tsandapps/console/src/loadLocales.ts;.changeset/12034-*.md.⛔ Not on it:
/i18ndispatcher domain answers an anonymous caller —handleI18nRequestmakes noshouldDenyAnonymouscall, unlike every other dispatcher domain (ADR-0056 D2); with an objectui companion for the Console sign-in page objectstack#22432) and the framework's.objectui-shapin;I18nProvideror onpackages/i18n. If the post-sign-in load cannot be built from the provider's existing API, the dev stops and reports it, and the seat routes it asClause-②;packages/i18nkey;examples/console-starter: the dev measures its loader and reports. It is not edited here, because the card names the Console.First-load bytes:
main.tsxis in the eager closure. The dev measures the delta against the ceiling of 3,281,467 B and stops before the PR above +1,024 B gzip.Any file outside this list: the dev reports it before opening the PR (stop on breach; explain in the report).
Container & model:
S,mode:subagent,model: opus(dispatch-gates --tier --repo objectstack-ai/objectuiover these paths: no path-derived mandate; default tier)Clause-②: no
Responsibility:
objectui Console: the sign-in page fetches /i18n anonymously, and nothing re-loads the application's translations with the session's credentials | the Console's I18nProvider loaders and its session state already on main | every Console user at sign-in, once objectstack-ai/objectstack#22432 refuses an anonymous /i18n readThread-read: none
Serial constraints cleared: no open objectui PR and no in-flight claim touches
apps/console/src/main.tsx,loadLanguage.tsorloadLocales.ts(read 2026-10-09T07:29Z).Order: this card lands first. objectstack-ai/objectstack#22432 is
Blocked-by:this card, and moves the framework's Console pin past this card's merge (card body).Why
Clause-②: no: the Console is an application, not a published package. Moving its translation load from boot to after sign-in changes no contract and no published prop. New provider props are excluded above.Generated by Claude Code
objectstack-fleet commentedon Oct 9, 2026
os-dev-report
{
"issue": 12034,
"status": "done",
"branch": "claude/issue-12034-console-i18n-after-signin",
"pr": "#12042",
"session": "session_01MgfduSkFrfM3eorB3UGfAU",
"head": "27caa7d0b",
"premise_still_valid": true,
"summary": "The console's two /i18n loaders (loadLanguage, loadLocales) now wait for this page load's session answer, published by the console AuthProvider's existing onAuthStateChange prop into a new console module (apps/console/src/i18nSession.ts). Signed out they send no request (the sign-in page renders from the built-in packs); signed in they read through withSettleSignal(createAuthenticatedFetch()), the data adapter's own request path (bearer, X-Tenant-ID, Accept-Language). No new prop, export or key on I18nProvider or packages/i18n. Premise partly corrected by measurement: the console already re-reads /i18n after sign-in, because every console sign-in exits by full-page navigation, but never with the bearer; and against the head of objectstack-ai/objectstack#22432, main shows signed-in users the untranslated authored literal, not raw keys.",
"hypotheses": {
"H1": "partly falsified. main blobs vs a fake framework refusing anonymous /i18n (bearer-only): sign-in page load made 2 reads (translations/zh, locales), no Authorization, both 401; the post-sign-in page load (LoginPage exits via window.location.assign, pinned by authExitBasename.test.tsx) made 2 more reads, no Authorization, both 401; heading stayed 'Lead'. Default credentials same-origin: on a same-origin cookie deployment the post-sign-in read would carry the cookie and be served; the bearer was never sent.",
"H2": "partly falsified. head: signed-in page load reads wait for AuthProvider's first answer (one get-session round trip), then carry Bearer, 200. 'First render already has the app labels' holds on neither main nor head: I18nProvider never holds first render for its loader; pin 2 shows Lead then the translation on one mounted heading.",
"H3": "holds with no re-run: existing loadLanguage/loadLocales props unchanged; the loader Promise settles on the session answer and the provider's own non-silent addResourceBundle (bindI18nStore 'added') re-renders. No key remount, no same-language changeLanguage (it would persist an explicit language choice). In-place sign-in is not re-run; the provider has no re-run hook (loadedAppLangs, askedForLocales guards).",
"H4": "holds by falling back, not waiting: sign-in page from the built-in zh pack; first signed-in render = built-in strings + authored literal; MutationObserver over every frame of sign-in to app: 0 raw keys (control catches a raw key). main also showed 0 raw keys: app-bundle readers fall back to the authored literal, and spec I18nLabel refuses the keyed {key, defaultValue} form (key?: never). Built-in call-site key coverage: check:i18n-keys green.",
"H5": "neutral: eagerGzipBytes base 049012b = 3,238,404 B, head 27caa7d = 3,238,537 B, delta +133 B gzip; ceiling 3,281,467 B. check:eager-closure: 'Console eager closure is 3162.6 KB gzipped across 289 of 2474 chunks (budget: 3204.6 KB, headroom: 41.9 KB)'."
},
"starter_measurement": "examples/console-starter (not edited): loader is a bare fetch, no loadLocales, and DefaultLoginPage signs in IN PLACE (navigate('/')). Probe with the starter's real loader vs the 401 framework: before sign-in 1 read, no Authorization, 401; after in-place sign-in 0 reads; heading stayed 'Lead' for the session. Once objectstack-ai/objectstack#22432 lands, starter users see untranslated app labels after sign-in until reload, on every deployment (the pre-sign-in read is anonymous everywhere and the provider never asks again); after reload same-origin cookie is served, bearer-only 401 again. The console's gate is not a drop-in there: in-place sign-in needs the page-load call to wait for a sign-in.",
"tests": "All at head 27caa7d (git rev-parse --short HEAD after the last commit). (1) pnpm exec vitest run over 40 files (3 touched/new test files; 31 apps/console suites mounting I18nProvider, LoginPage or App; 7 suites reading main.tsx/App.tsx source: bootSplash, insecure-origin-crypto.placement, faviconAfterNavigation, tabTitleAfterNavigation, consoleToasterAnchor.ratchet-7482, auth-namespace-3546, runtimeConfigBootDedup; column-identity.ratchet; one-authority-per-exported-name-6273): 'Test Files 40 passed (40)', 'Tests 290 passed (290)', lock VERDICT command-exit 0. (2) reverse leg: loadLanguage.ts, loadLocales.ts, App.tsx, main.tsx swapped for main's blobs (hash == 049012b blob each): pins + loader tests 'Tests 7 failed | 13 passed (20)' (red: pins 1,2,3 + 4 new loader session-rule tests; green: control + pre-existing loader tests); restore via git checkout HEAD, each hash == HEAD blob, git diff HEAD = 0 bytes. (3) wire ablation (only onAuthStateChange={publishAuthState} removed from App.tsx; anchor count 1 to 0): 'Tests 2 failed | 2 passed (4)' (pins 2,3 red; pin 1 + control green as expected); restore proven by hash, git diff HEAD = 0 bytes. All mutation scripts carried trap restore EXIT INT TERM.",
"gates": [
"pnpm --filter @object-ui/console type-check (closure built first: turbo run build --filter=@object-ui/console^... --concurrency=2, VERDICT command-exit 0): echoed 'tsc --noEmit && tsc -b tsconfig.node.json --force', VERDICT command-exit 0; --listFiles includes the 3 test files",
"pnpm exec eslint (8 touched files, --format json): files 8, errors 0, warnings 0, exit 0",
"node scripts/check-changeset-presence.mjs: '8 source file(s) of 1 released package(s) changed, and this change declares 1 changeset(s)', exit 0",
"node scripts/check-changeset-no-major.mjs: 'No changeset declares a major bump', exit 0",
"pnpm check:new-line-citations: 'VERDICT new-cross-file-line-citations: 0 new citation(s), enforcement report-only', then an arrow and 'exit 0' (arrow spelled out for the body sanitizer)",
"pnpm check:control-bytes: 'check-control-bytes: OK (scanned 8189 tracked text file(s); skipped 85 binary)', exit 0",
"pnpm check:i18n-keys: 'Every in-scope call-site key resolves against the en pack (3311 keys) ...', exit 0",
"pnpm check:vi-mock-specifiers / vi-mock-inherit / vi-mock-override-shape: OK, exit 0 each",
"pnpm check:test-path-roots: OK, exit 0",
"pnpm check:changeset-claims: 'No pending changeset names a file this change touches', exit 0",
"pnpm check:pending-changeset-literals: 'No test source names a pending changeset', exit 0",
"pnpm check:unreferenced-sources: 'OK Every shipped source file in every covered package is reachable', exit 0",
"pnpm check:phantom-deps: 'Every in-scope import is declared by the package that publishes it', exit 0",
"pnpm check:eager-closure: 'Console eager closure is 3162.6 KB gzipped across 289 of 2474 chunks (budget: 3204.6 KB, headroom: 41.9 KB)', exit 0",
"node scripts/check-governed-queue-guard.mjs --test (9 paths): 'NOT GOVERNED'",
"NOT MEASURED locally, declared to CI: repo-wide pnpm lint and full pnpm test. docs:check-links and check:spec-symbols not applicable (content/docs untouched)."
],
"eager_closure": {
"base_049012bf0": 3238404,
"head_27caa7d0b": 3238537,
"delta_gzip_bytes": 133,
"ceiling": 3281467,
"ci_budget_bot_reading": "NOT MEASURED: reported after CI by the seat"
},
"files_changed": [
"apps/console/src/i18nSession.ts (new: the session state the post-sign-in load hangs on)",
"apps/console/src/App.tsx (AuthProvider onAuthStateChange={publishAuthState})",
"apps/console/src/loadLanguage.ts",
"apps/console/src/loadLocales.ts",
"apps/console/src/main.tsx (comment only)",
"apps/console/src/loadLanguage.test.tsx",
"apps/console/src/loadLocales.test.ts",
"apps/console/src/tests/i18nAfterSignIn-12034.test.tsx (the card's three pins + a control)",
".changeset/12034-console-i18n-after-signin.md (@object-ui/console: patch)"
],
"docs": "none: no content/docs page describes the console's translation loading; guide/console.md and guide/deployment.md only say the i18n endpoints hang off VITE_SERVER_URL, still true. No docs edit.",
"deviations": [
"The session-state file was named in the PR body and this report, not before the edit: App.tsx (the console's AuthProvider mount) plus a new console module apps/console/src/i18nSession.ts, read as the claim's third bullet.",
"Claim says the Console is 'an application, not a published package'. Measured: @object-ui/console is published (publishConfig.access public, files dist) and in the changesets fixed group; AGENTS.md section 9 Housekeeping requires a changeset for its src, so a patch changeset ships. Clause-2: no still holds (no export, prop or contract change).",
"Commit trailers follow objectui AGENTS.md's model-free pair (Claude-Session + 'Co-authored-by: Claude') instead of the harness reminder's model-named trailer; PR footer uses the agent definition's session-URL form instead of the harness's form.",
"Two temporary probe test files (one in apps/console, one in examples/console-starter) were created, run and deleted, never committed; a detached base worktree was created for the base build and removed.",
"Zero label writes: objectui path labels (apps, tests) were the labeler's; the dispatch named none. Only the PR assignee was written."
],
"mcp_calls": "0",
"api_writes": "3 REST writes through the fleet-write relay (each one POST /repos/objectstack-ai/objectstack/dispatches): pr_create (draft PR #12042, read-back identical 11948 bytes), label-write assign os-bill on PR #12042 (read-back MATCHES), and this os-dev-report comment on #12034. Plus 4 git pushes of the branch (empty-branch probe, then 3 commits' pushes), not REST.",
"open_questions": [],
"out_of_scope_findings": [
"class: a · reach: public door, the console-starter's sign-in (app-shell DefaultLoginPage signs in in place with navigate('/')) against the head of objectstack-ai/objectstack#22432: the app labels stay untranslated for the whole session after sign-in; measured by probe (1 anonymous 401 read before sign-in, 0 reads after, heading 'Lead'). Contingent on objectstack-ai/objectstack#22432 landing; the dispatch asked for this measurement, not an edit. Any host pairing app-shell's DefaultLoginPage with an I18nProvider loader has the same shape, and I18nProvider has no re-run hook after an in-place sign-in, so a fix may need a provider API (Clause-2 territory). · dedupe words: console-starter, in-place sign-in, loadLanguage, i18n 401, DefaultLoginPage",
"carrier: the seat routing objectstack-ai/objectstack#22432 · noted, not filed: if objectstack-ai/objectstack#22432 should also wait on a starter companion, that ordering is the seat's call"
]
}
Generated by Claude Code
objectstack-fleet commentedon Oct 9, 2026
Review: ACCEPT — PR objectui#12042 (
Fixes) ·domain:uiseat 2 · 2026-10-09T08:19ZImplemented-by:
os-devsubagent ofsession_01MgfduSkFrfM3eorB3UGfAU, branchclaude/issue-12034-console-i18n-after-signin, head27caa7d.Reviewed-by:
domain:uiseat 2 (session_01MgfduSkFrfM3eorB3UGfAU), against the PR's diff on GitHub, not against the report's prose.Built:
apps/console/src/i18nSession.ts(new) holds the consoleAuthProvider's answer for the page load.App.tsxfeeds it through that provider's existingonAuthStateChangeprop.loadLanguageandloadLocaleswait for that answer:{}/[], so the sign-in page renders from the built-in packs;withSettleSignal(createAuthenticatedFetch()), the data adapter's own request path (bearer,X-Tenant-ID,Accept-Language). No token is lifted from storage, as the claim required.I18nProvideris used through its existing props. No published prop, export orpackages/i18nkey is added, soClause-②: noholds.The card's premise, corrected by measurement (accepted):
/i18nafter sign-in, because every console sign-in exits by a full-page navigation (window.location.assign, pinned byauthExitBasename.test.tsx). What it never did was send the bearer./i18ndispatcher domain answers an anonymous caller —handleI18nRequestmakes noshouldDenyAnonymouscall, unlike every other dispatcher domain (ADR-0056 D2); with an objectui companion for the Console sign-in page objectstack#22432,mainshowed a signed-in user the untranslated authored literal (Lead), not raw keys. On head, the signed-in page load reads with the bearer and gets 200.MutationObserverover every frame from sign-in to app records zero, and its control catches a key drawn raw.Checklist:
PR shape: draft, first line
Fixes #12034,Clause-②: noat the start of a line. runtime: the/i18ndispatcher domain answers an anonymous caller —handleI18nRequestmakes noshouldDenyAnonymouscall, unlike every other dispatcher domain (ADR-0056 D2); with an objectui companion for the Console sign-in page objectstack#22432 is named with no closing keyword. The assignee isos-bill. Commit trailers carry no model name.Scope: 9 files, all inside the claim:
App.tsx(one prop);main.tsx(a comment only);@object-ui/console: patch.The session module was named in the report rather than before the edit; the claim's third bullet allowed it.
Changeset: the claim called the Console an application. Measured,
@object-ui/consoleis published and in thefixedgroup, so AGENTS.md §9 asks for a changeset. Accepted.Reverse legs:
main's blobs, 7 of 20 tests turn red (pins 1–3 and the four new loader-session tests).onAuthStateChangewire turns pins 2 and 3 red.blob == HEAD.Evidence:
check:i18n-keys,check:phantom-deps,check:unreferenced-sources, both changeset checks andcheck:eager-closurepass.Docs: no
content/docspage describes the Console's translation loading.guide/console.mdandguide/deployment.mdonly say the endpoints hang offVITE_SERVER_URL, which stays true.First-load bytes: +133 B gzip (3,238,404 → 3,238,537 B), with 41.9 KB of headroom. The seat's sum of accepted, unlanded deltas is +133 B: PR objectui#12040 is +0 B, and PR objectui#12036 is not accepted.
CI:
27caa7dis running. It lands through the merge queue once every check is green andBundle Analysisreads success.Order: this card lands first. objectstack-ai/objectstack#22432 is
pm:blockedwithBlocked-by:this card, and its own PR moves the framework's Console pin past this merge.Noted for objectstack-ai/objectstack#22432, not this card:
examples/console-startersigns in in place, so once #22432 lands its users see untranslated application labels until they reload. That pointer is carried on #22432 itself.Generated by Claude Code