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
The by_unit lens shows 151 finished tasks and pages out a whole business unit — scope it to open work #86
Observation, not a regression — noticed while verifying #76 in the browser and deliberately kept out of that PR.
Measured
With #76's fix in place (business_unit now fetched), /_console/apps/ai.objectstack.duly/duly_task/view/by_unit on the #75 seed renders:
Business unit ▸ Northgate Operations 33
Business unit ▸ Northgate Plant 3
Business unit ▸ Northgate Quality 46
Business unit ▸ Riverside Plant 18
───
100 ← "100 records · Showing first 100 records."
The grouping is client-side over the fetched page. The request is top=100, and the store holds 186 tasks across five business units — 61 / 86 / 31 / 7 / 1 per the count in #76. So:
one business unit has no group at all on page 1, and nothing on screen says a unit is missing;
the counts that are shown are page slices, not totals (the largest unit holds 86 rows in the store; its header reads 46).
Why it is worth a card rather than a shrug
The footer does disclose "Showing first 100 records. More data may be available." — but the number that reads as authoritative is the one in the group header, next to the unit's name, and that number is a slice. This is the same shape as #76 itself: nothing errors, the screen is internally consistent, and it reads as data rather than as a bug. A manager's org lens is exactly where a partial count is most likely to be taken as a total.
Note that #76's own acceptance criterion says "counts summing to the visible row total", so the page scoping was known and accepted there. This card is only about whether it should stay that way, and it is unmeasured beyond the above — no view has been changed for it.
Options, unranked
Leave it. Grouping is a page-level convenience; the footer already discloses the truncation.
Raise the page size on the grouped lens if the view schema exposes it — cheap, and it moves the cliff rather than removing it.
Server-side grouping / aggregate counts — the honest fix, and probably a platform capability question rather than an app one (the dashboard's "Not moving, by business unit" chart already groups server-side through a dataset and gets true totals).
No file is assigned; needs triage rather than an implementation.
Triaged — and none of the three options is the answer. The view is paging because it is showing the wrong rows.
First, the platform question, because it decides what is even available. Checked in objectui: useGroupedData groups over data — the rows already in the browser — and its per-group aggregations are computeAggregations(entry.rows, …) over that same array. There is no server-side grouping path for a grid at all. So option 3 is not something we can reach declaratively; it is a platform capability request, not an app change.
That means a grouped grid can never be a complete org roll-up while the store outgrows a page. Which reframes the card: the question is not how to make the counts true, it is why this lens is paging in the first place.
It is paging because it shows 151 finished tasks
by_unit carries no filter. It renders all 186 tasks — 151 of them done, most from months ago — and the manager's org lens spends its entire first page on completed work before it reaches anything actionable. The page cliff is a symptom.
Filter the lens to open work and both problems go at once: 27 open + 6 in_progress = 33 rows, one page, every unit present, every count true. And it is the better lens on its own merits — "what is outstanding, by unit" is the question a manager opens this for. Nobody has ever wanted a by-unit breakdown of work that is already finished.
That is not a workaround dressed as design, and the test is that it survives the platform being fixed: if server-side grouping ships tomorrow, we would still not want this lens showing six months of completed tasks.
Decision
Scope by_unit to open work (status IN ('open','in_progress')), and say in the view comment that completeness of the grouping is why the filter is load-bearing rather than a default worth inheriting — otherwise someone widens it later and silently reintroduces this.
Do not raise the page size. It moves the cliff and hides the next occurrence; with a filter that fits, the page size is not what is holding the lens together.
File the server-side grouping gap upstream — that is the durable answer, and it should exist whether or not we need it today. Note in it that the dashboard already gets true by-unit totals through a dataset, so the platform has the capability, just not on this surface.
Even filtered, this remains structurally page-scoped: a deployment with 200 open tasks hits it again, and the failure is still silent — a missing group, with nothing on screen saying a unit is absent. The filter buys us a correct lens at this product's realistic scale, not a correct mechanism.
So the group-header count keeps a hazard we cannot remove from here, and the missing group is the sharper half of it: a wrong number invites a second look, a missing unit does not. Until upstream lands, the honest position is that the dashboard is the authoritative by-unit surface and this lens is for browsing. Worth a line in the view's description saying so.
changed the title [-]Grouped grid counts are page-scoped, and the group header does not say so — `by_unit` shows 4 of 5 units[/-][+]The by_unit lens shows 151 finished tasks and pages out a whole business unit — scope it to open work[/+]on Sep 1, 2026
Working to the triage comment as the specification, not the three options in the card body: scope by_unit to status IN ('open','in_progress'), say in the view comment that the filter is load-bearing for grouping completeness, state the residual page-scoping in the view description, and add the guard alongside #85's grouping guard in test/metadata-bindings.test.ts. Not raising the page size. The upstream platform gap is already filed as objectstack-ai/objectui#7189 — referencing it rather than filing a duplicate.
{
"issue": 86,
"status": "done",
"branch": "claude/issue-86-by-unit-open-work",
"pr": "https://github.com/objectstack-ai/duly/pull/91",
"premise_still_valid": true,
"summary": "Implemented the triage comment's scope, not the card body's three options. `duly_task > by_unit` now carries `status in ('open','in_progress')`; the page size is untouched. The view comment states that the filter is load-bearing for grouping completeness rather than a default worth inheriting, and the view's `description` states the residual (dashboard is the authoritative by-unit surface, this lens is for browsing). The guard lives in `test/metadata-bindings.test.ts` alongside #85's grouping-projection guard and in its idiom: it pins the by_unit decision and inventories every grouped grid with the scope it carries, which doubles as the non-vacuity counter. Scoped to a pin rather than a 'grouped grids must be filtered' rule by measurement -- that rule would fire on `duly_duty > catalog_tree`, which groups two levels, carries no filter, and does not need one (31 duties, one page). Upstream gap referenced as objectui#7189, not duplicated. One caveat found while verifying and reported honestly rather than papered over: the `description` is served (`GET /api/v1/meta/view/duly_task` carries it) but never rendered, because the console's ObjectView relay does not copy a per-view `description` onto the ListView schema -- filed as objectui#7199, said plainly in the view comment, and NOT overclaimed in the PR body.",
"tests": "All four gates green on the final commit b780718, run as one union after the last commit: `pnpm validate && pnpm typecheck && pnpm test && pnpm build` -> exit 0; 'Validation passed (428ms)', 'Test Files 22 passed (22) / Tests 591 passed (591)', 'Build complete', 'Artifact: dist/objectstack.json (278.4 KB)'. validate prints only the expected hierarchy-security capability warning AGENTS.md documents as this repo's normal state. Exit codes captured before any pipe (redirect-then-tail), and the verdicts quoted are the gates' own printed lines. New guard: 9 cases, all confirmed executed by name via `--reporter=verbose` (not inferred from a green total). REVERSE VERIFICATION: fix committed FIRST, then `git checkout origin/main -- src/views/task.view.ts` restored the pre-fix view (post-#85, pre-#86), with restore through a `trap ... EXIT INT TERM`. Mutation confirmed on disk by anchored fixed-string greps on the text being removed, not by the editor's exit code: open-work filter lines 0 (want 0), pre-fix doc phrase 1 (want 1). Guard then exited 1 on BOTH assertions -- 'expected [] to deeply equal [ in_progress, open ]' and the inventory line flipping to 'status scope: (none)'. Restored, `git diff HEAD` empty, 52 tests green again. BROWSER VERIFICATION on the seeded app (own dev server on port 3186 from my worktree, never the shared one on 3000; artifact rebuilt by the dev watcher for each leg, and the leg's metadata confirmed on disk before reading any result). Before (only my filter reverted, same server/session/seed): 4 groups -- Operations 33, Plant 3, Quality 46, Riverside 18 = 100, footer '100 records - Showing first 100 records. More data may be available.', CENTRAL OFFICE ABSENT, reproducing the card's measurement exactly. After: 5 groups -- Central Office 1, Northgate Operations 7, Northgate Plant 1, Northgate Quality 18, Riverside Plant 6; header counts sum to 33, footer '33 records' with no truncation notice, 33 visible data rows, and the request carries `filter=[[\"status\",\"in\",[\"open\",\"in_progress\"]]]` with `top=100`. Independently counted off the seed and matching row for row: 186 rows total, 151 done, 27 open + 6 in_progress = 33 across all five units (18/7/6/1/1). Screenshot captured. Cleanup: my dev server and Chromium killed by recorded PID only (never `pkill -f`, which would match the Claude CLI itself), worktree removed without --force.",
"open_questions": [],
"out_of_scope_findings": [
"filed as objectstack-ai/objectui#7199: a list view's `description` is served (`GET /api/v1/meta/view/<object>`) but never rendered -- app-shell's ObjectView relay copies `label`/`sort`/`filter` off the active view onto the ListView schema and never copies `description`, so ListView's `data-testid=view-description` branch never receives a value; includes a second half, that ListView renders `typeof description === 'string' ? description : ''`, so an inline `{en,'zh-CN'}` locale map would render empty even after the relay is fixed. Searched objectui for duplicates first; none open. Not fixed here -- different repo, different defect class, not covered by this card's gates."
]
}
Supersedes the previous comment on this issue: its <!-- os-dev-report --> HTML-comment marker did not survive GitHub's body sanitizer (the comment was stored starting at the code fence, with the marker gone), so it is unfindable by a marker scan. The marker is written as literal text on the first line here. Same report, no content change.
{
"issue": 86,
"status": "done",
"branch": "claude/issue-86-by-unit-open-work",
"pr": "https://github.com/objectstack-ai/duly/pull/91",
"premise_still_valid": true,
"summary": "Implemented the triage comment's scope, not the card body's three options. duly_task by_unit now carries `status in ('open','in_progress')`; the page size is untouched. The view comment states that the filter is load-bearing for grouping completeness rather than a default worth inheriting, and the view's `description` states the residual (dashboard is the authoritative by-unit surface, this lens is for browsing). The guard lives in `test/metadata-bindings.test.ts` alongside #85's grouping-projection guard and in its idiom: it pins the by_unit decision and inventories every grouped grid with the scope it carries, which doubles as the non-vacuity counter. Scoped to a pin rather than a 'grouped grids must be filtered' rule by measurement -- that rule would fire on duly_duty catalog_tree, which groups two levels, carries no filter, and does not need one (31 duties, one page). Upstream gap referenced as objectui#7189, not duplicated. One caveat found while verifying and reported rather than papered over: the `description` is served (`GET /api/v1/meta/view/duly_task` carries it) but never rendered, because the console's ObjectView relay does not copy a per-view `description` onto the ListView schema -- filed as objectui#7199, said plainly in the view comment, and NOT overclaimed in the PR body.",
"tests": "All four gates green on the final commit b780718, run as one union after the last commit: `pnpm validate && pnpm typecheck && pnpm test && pnpm build` exit 0; 'Validation passed (428ms)', 'Test Files 22 passed (22) / Tests 591 passed (591)', 'Build complete', 'Artifact: dist/objectstack.json (278.4 KB)'. validate prints only the expected hierarchy-security capability warning AGENTS.md documents as this repo's normal state. Exit codes captured before any pipe (redirect-then-tail); the verdicts quoted are the gates' own printed lines. New guard: 9 cases, all confirmed executed by name via --reporter=verbose, not inferred from a green total. REVERSE VERIFICATION: fix committed FIRST, then `git checkout origin/main -- src/views/task.view.ts` restored the pre-fix view (post-#85, pre-#86), restore through a trap on EXIT INT TERM. Mutation confirmed on disk by anchored fixed-string greps on the text being removed, not by the editor's exit code: open-work filter lines 0 (want 0), pre-fix doc phrase 1 (want 1). The guard then exited 1 on BOTH assertions -- 'expected [] to deeply equal [ in_progress, open ]' and the inventory line flipping to 'status scope: (none)'. Restored; `git diff HEAD` empty; 52 tests green again. BROWSER VERIFICATION on the seeded app (my own dev server on port 3186 from my worktree, never the shared one on 3000; the dev watcher rebuilt the artifact for each leg and the leg's metadata was confirmed on disk before any result was read). Before (only my filter reverted, same server/session/seed): 4 groups -- Operations 33, Plant 3, Quality 46, Riverside 18 = 100, footer '100 records - Showing first 100 records. More data may be available.', CENTRAL OFFICE ABSENT, reproducing the card's measurement exactly. After: 5 groups -- Central Office 1, Northgate Operations 7, Northgate Plant 1, Northgate Quality 18, Riverside Plant 6; header counts sum to 33, footer '33 records' with no truncation notice, 33 visible data rows, and the grid's request carries the status-in-open-in_progress filter with top=100. Independently counted off the seed and matching row for row: 186 rows total, 151 done, 27 open + 6 in_progress = 33 across all five units (18/7/6/1/1). Screenshot captured. Cleanup: dev server and Chromium killed by recorded PID only (never pkill -f, which would match the Claude CLI itself); worktree removed without --force.",
"open_questions": [],
"out_of_scope_findings": [
"filed as objectstack-ai/objectui#7199: a list view's `description` is served (GET /api/v1/meta/view/<object>) but never rendered -- app-shell's ObjectView relay copies label/sort/filter off the active view onto the ListView schema and never copies description, so ListView's data-testid=view-description branch never receives a value. Includes a second half: ListView renders `typeof description === 'string' ? description : ''`, so an inline {en,'zh-CN'} locale map would render empty even after the relay is fixed. Searched objectui for duplicates first; none open. Not fixed here -- different repo, different defect class, not covered by this card's gates."
]
}
Activity
os-warren commentedon Sep 1, 2026
Triaged — and none of the three options is the answer. The view is paging because it is showing the wrong rows.
First, the platform question, because it decides what is even available. Checked in objectui:
useGroupedDatagroups overdata— the rows already in the browser — and its per-group aggregations arecomputeAggregations(entry.rows, …)over that same array. There is no server-side grouping path for a grid at all. So option 3 is not something we can reach declaratively; it is a platform capability request, not an app change.That means a grouped grid can never be a complete org roll-up while the store outgrows a page. Which reframes the card: the question is not how to make the counts true, it is why this lens is paging in the first place.
It is paging because it shows 151 finished tasks
by_unitcarries no filter. It renders all 186 tasks — 151 of themdone, most from months ago — and the manager's org lens spends its entire first page on completed work before it reaches anything actionable. The page cliff is a symptom.Filter the lens to open work and both problems go at once: 27
open+ 6in_progress= 33 rows, one page, every unit present, every count true. And it is the better lens on its own merits — "what is outstanding, by unit" is the question a manager opens this for. Nobody has ever wanted a by-unit breakdown of work that is already finished.That is not a workaround dressed as design, and the test is that it survives the platform being fixed: if server-side grouping ships tomorrow, we would still not want this lens showing six months of completed tasks.
Decision
by_unitto open work (status IN ('open','in_progress')), and say in the view comment that completeness of the grouping is why the filter is load-bearing rather than a default worth inheriting — otherwise someone widens it later and silently reintroduces this.by_unitlens must carry a status filter. Cheap, and it is the thing that stops (1) being quietly undone.The part that stays broken, and must be said
Even filtered, this remains structurally page-scoped: a deployment with 200 open tasks hits it again, and the failure is still silent — a missing group, with nothing on screen saying a unit is absent. The filter buys us a correct lens at this product's realistic scale, not a correct mechanism.
So the group-header count keeps a hazard we cannot remove from here, and the missing group is the sharper half of it: a wrong number invites a second look, a missing unit does not. Until upstream lands, the honest position is that the dashboard is the authoritative by-unit surface and this lens is for browsing. Worth a line in the view's description saying so.
Queueing with that scope.
Generated by Claude Code
[-]Grouped grid counts are page-scoped, and the group header does not say so — `by_unit` shows 4 of 5 units[/-][+]The by_unit lens shows 151 finished tasks and pages out a whole business unit — scope it to open work[/+]os-warren commentedon Sep 1, 2026
Claiming this card.
session_01SqkTcrxUFci7nqXdbBSe2pclaude/issue-86-by-unit-open-work../duly-issue-86offorigin/mainWorking to the triage comment as the specification, not the three options in the card body: scope
by_unittostatus IN ('open','in_progress'), say in the view comment that the filter is load-bearing for grouping completeness, state the residual page-scoping in the viewdescription, and add the guard alongside #85's grouping guard intest/metadata-bindings.test.ts. Not raising the page size. The upstream platform gap is already filed as objectstack-ai/objectui#7189 — referencing it rather than filing a duplicate.Generated by Claude Code
Scope the by-unit lens to open work (#86)
os-warren commentedon Sep 1, 2026
{ "issue": 86, "status": "done", "branch": "claude/issue-86-by-unit-open-work", "pr": "https://github.com/objectstack-ai/duly/pull/91", "premise_still_valid": true, "summary": "Implemented the triage comment's scope, not the card body's three options. `duly_task > by_unit` now carries `status in ('open','in_progress')`; the page size is untouched. The view comment states that the filter is load-bearing for grouping completeness rather than a default worth inheriting, and the view's `description` states the residual (dashboard is the authoritative by-unit surface, this lens is for browsing). The guard lives in `test/metadata-bindings.test.ts` alongside #85's grouping-projection guard and in its idiom: it pins the by_unit decision and inventories every grouped grid with the scope it carries, which doubles as the non-vacuity counter. Scoped to a pin rather than a 'grouped grids must be filtered' rule by measurement -- that rule would fire on `duly_duty > catalog_tree`, which groups two levels, carries no filter, and does not need one (31 duties, one page). Upstream gap referenced as objectui#7189, not duplicated. One caveat found while verifying and reported honestly rather than papered over: the `description` is served (`GET /api/v1/meta/view/duly_task` carries it) but never rendered, because the console's ObjectView relay does not copy a per-view `description` onto the ListView schema -- filed as objectui#7199, said plainly in the view comment, and NOT overclaimed in the PR body.", "tests": "All four gates green on the final commit b780718, run as one union after the last commit: `pnpm validate && pnpm typecheck && pnpm test && pnpm build` -> exit 0; 'Validation passed (428ms)', 'Test Files 22 passed (22) / Tests 591 passed (591)', 'Build complete', 'Artifact: dist/objectstack.json (278.4 KB)'. validate prints only the expected hierarchy-security capability warning AGENTS.md documents as this repo's normal state. Exit codes captured before any pipe (redirect-then-tail), and the verdicts quoted are the gates' own printed lines. New guard: 9 cases, all confirmed executed by name via `--reporter=verbose` (not inferred from a green total). REVERSE VERIFICATION: fix committed FIRST, then `git checkout origin/main -- src/views/task.view.ts` restored the pre-fix view (post-#85, pre-#86), with restore through a `trap ... EXIT INT TERM`. Mutation confirmed on disk by anchored fixed-string greps on the text being removed, not by the editor's exit code: open-work filter lines 0 (want 0), pre-fix doc phrase 1 (want 1). Guard then exited 1 on BOTH assertions -- 'expected [] to deeply equal [ in_progress, open ]' and the inventory line flipping to 'status scope: (none)'. Restored, `git diff HEAD` empty, 52 tests green again. BROWSER VERIFICATION on the seeded app (own dev server on port 3186 from my worktree, never the shared one on 3000; artifact rebuilt by the dev watcher for each leg, and the leg's metadata confirmed on disk before reading any result). Before (only my filter reverted, same server/session/seed): 4 groups -- Operations 33, Plant 3, Quality 46, Riverside 18 = 100, footer '100 records - Showing first 100 records. More data may be available.', CENTRAL OFFICE ABSENT, reproducing the card's measurement exactly. After: 5 groups -- Central Office 1, Northgate Operations 7, Northgate Plant 1, Northgate Quality 18, Riverside Plant 6; header counts sum to 33, footer '33 records' with no truncation notice, 33 visible data rows, and the request carries `filter=[[\"status\",\"in\",[\"open\",\"in_progress\"]]]` with `top=100`. Independently counted off the seed and matching row for row: 186 rows total, 151 done, 27 open + 6 in_progress = 33 across all five units (18/7/6/1/1). Screenshot captured. Cleanup: my dev server and Chromium killed by recorded PID only (never `pkill -f`, which would match the Claude CLI itself), worktree removed without --force.", "open_questions": [], "out_of_scope_findings": [ "filed as objectstack-ai/objectui#7199: a list view's `description` is served (`GET /api/v1/meta/view/<object>`) but never rendered -- app-shell's ObjectView relay copies `label`/`sort`/`filter` off the active view onto the ListView schema and never copies `description`, so ListView's `data-testid=view-description` branch never receives a value; includes a second half, that ListView renders `typeof description === 'string' ? description : ''`, so an inline `{en,'zh-CN'}` locale map would render empty even after the relay is fixed. Searched objectui for duplicates first; none open. Not fixed here -- different repo, different defect class, not covered by this card's gates." ] }Generated by Claude Code
os-warren commentedon Sep 1, 2026
os-dev-report
{ "issue": 86, "status": "done", "branch": "claude/issue-86-by-unit-open-work", "pr": "https://github.com/objectstack-ai/duly/pull/91", "premise_still_valid": true, "summary": "Implemented the triage comment's scope, not the card body's three options. duly_task by_unit now carries `status in ('open','in_progress')`; the page size is untouched. The view comment states that the filter is load-bearing for grouping completeness rather than a default worth inheriting, and the view's `description` states the residual (dashboard is the authoritative by-unit surface, this lens is for browsing). The guard lives in `test/metadata-bindings.test.ts` alongside #85's grouping-projection guard and in its idiom: it pins the by_unit decision and inventories every grouped grid with the scope it carries, which doubles as the non-vacuity counter. Scoped to a pin rather than a 'grouped grids must be filtered' rule by measurement -- that rule would fire on duly_duty catalog_tree, which groups two levels, carries no filter, and does not need one (31 duties, one page). Upstream gap referenced as objectui#7189, not duplicated. One caveat found while verifying and reported rather than papered over: the `description` is served (`GET /api/v1/meta/view/duly_task` carries it) but never rendered, because the console's ObjectView relay does not copy a per-view `description` onto the ListView schema -- filed as objectui#7199, said plainly in the view comment, and NOT overclaimed in the PR body.", "tests": "All four gates green on the final commit b780718, run as one union after the last commit: `pnpm validate && pnpm typecheck && pnpm test && pnpm build` exit 0; 'Validation passed (428ms)', 'Test Files 22 passed (22) / Tests 591 passed (591)', 'Build complete', 'Artifact: dist/objectstack.json (278.4 KB)'. validate prints only the expected hierarchy-security capability warning AGENTS.md documents as this repo's normal state. Exit codes captured before any pipe (redirect-then-tail); the verdicts quoted are the gates' own printed lines. New guard: 9 cases, all confirmed executed by name via --reporter=verbose, not inferred from a green total. REVERSE VERIFICATION: fix committed FIRST, then `git checkout origin/main -- src/views/task.view.ts` restored the pre-fix view (post-#85, pre-#86), restore through a trap on EXIT INT TERM. Mutation confirmed on disk by anchored fixed-string greps on the text being removed, not by the editor's exit code: open-work filter lines 0 (want 0), pre-fix doc phrase 1 (want 1). The guard then exited 1 on BOTH assertions -- 'expected [] to deeply equal [ in_progress, open ]' and the inventory line flipping to 'status scope: (none)'. Restored; `git diff HEAD` empty; 52 tests green again. BROWSER VERIFICATION on the seeded app (my own dev server on port 3186 from my worktree, never the shared one on 3000; the dev watcher rebuilt the artifact for each leg and the leg's metadata was confirmed on disk before any result was read). Before (only my filter reverted, same server/session/seed): 4 groups -- Operations 33, Plant 3, Quality 46, Riverside 18 = 100, footer '100 records - Showing first 100 records. More data may be available.', CENTRAL OFFICE ABSENT, reproducing the card's measurement exactly. After: 5 groups -- Central Office 1, Northgate Operations 7, Northgate Plant 1, Northgate Quality 18, Riverside Plant 6; header counts sum to 33, footer '33 records' with no truncation notice, 33 visible data rows, and the grid's request carries the status-in-open-in_progress filter with top=100. Independently counted off the seed and matching row for row: 186 rows total, 151 done, 27 open + 6 in_progress = 33 across all five units (18/7/6/1/1). Screenshot captured. Cleanup: dev server and Chromium killed by recorded PID only (never pkill -f, which would match the Claude CLI itself); worktree removed without --force.", "open_questions": [], "out_of_scope_findings": [ "filed as objectstack-ai/objectui#7199: a list view's `description` is served (GET /api/v1/meta/view/<object>) but never rendered -- app-shell's ObjectView relay copies label/sort/filter off the active view onto the ListView schema and never copies description, so ListView's data-testid=view-description branch never receives a value. Includes a second half: ListView renders `typeof description === 'string' ? description : ''`, so an inline {en,'zh-CN'} locale map would render empty even after the relay is fixed. Searched objectui for duplicates first; none open. Not fixed here -- different repo, different defect class, not covered by this card's gates." ] }Generated by Claude Code