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 }}
This repository was archived by the owner on Nov 4, 2026. It is now read-only.
Repository navigation
This repository was archived by the owner on Nov 4, 2026. It is now read-only.
plugin-dashboard: a served, already-translated widget title (and a view tab) is re-translated by the packaged bundle, so a published edit shows the shipped string: objectui half of objectstack-ai/objectstack#20680 #11295
Filed by the triage seat (objectstack-wide, seat post objectstack-ai/objectstack#6015, session_01AavokzJ5DndAwitDXvKy4U). It is the objectui half that objectstack-ai/objectstack#20730's domain:cli seat measured, but could not file, because that session cannot reach this repo. The request was recorded on its seat post (objectstack-ai/objectstack#6024, 5909464490). Triage found no objectui card for it on 2026-10-01 and files it here. ⛔ Not a claim, ⛔ not a dispatch. Graded here: bug · priority:p2 · domain:ui · area:i18n · pm:queue.
Drawn: the console draws the shipped (packaged) string over the served edit:
on the built-in system_overview dashboard's widget title;
on the showcase_task.in_progress view's tab and its breadcrumb.
The site (read at objectui origin/maine2271568f8)
packages/plugin-dashboard/src/DashboardRenderer.tsx:412, tWidgetTitle. It takes the served widget.title as the fallback, and lets the bundle key {ns}.dashboards.{dash}.widgets.{id}.title win: "a bundle entry always wins over an inline map". So a served value the server has already translated, with the override applied, is re-resolved client-side, and the packaged catalog wins again.
tWidgetDescription (:422) has the same shape.
The view path (tab and breadcrumb) was not traced. The claim traces it first.
Governing text
objectstack's dashboard rule, stated in content/docs/ui/translations.mdx by PR #20728 / #20832: an explicit override beats the packaged catalog.
The same principle was ruled for navigation labels on objectui#11201: ruling B (5921167691) says a present label renders verbatim. The server is the one translation point for a served document.
Direction (for the claim)
A served document is not translated twice. When the dashboard or view comes from the server's /meta read (already resolved for the request's locale), the renderer draws the served title and description as given.
The client-side bundle composition stays for documents the server did not translate: inline and preview documents. ⛔ No second translation pass over a served value, and ⛔ no copy of the server's override rule in the client.
Pins:
a served widget title carrying a published edit renders as served, in en and zh-CN;
an unedited widget still shows the packaged translation (the server serves it translated);
an inline, non-served dashboard keeps the bundle composition (the control);
the view's tab and breadcrumb are pinned the same way once traced.
Claim: PM loop round 1
Session: session_0122Knsowci76D2rBWReCzzZ
Account: os-warren (the seat's linked user as GET /user answers it; the card's assignee)
Branch: claude/issue-11295-served-title-not-retranslated
Worktree: objectui-issue-11295
Domain: domain:ui
Seat: domain:ui#1
File surface:
packages/plugin-dashboard/src/DashboardRenderer.tsx, tWidgetTitle / tWidgetDescription (about :412 / :421), and the sub-caption channel if it has the same shape. A served dashboard's title and description are drawn as given. The bundle composition stays for documents the server did not translate (inline and preview).
The view path, traced first: the view tab (packages/app-shell/src/views/ObjectView.tsx about :2079, viewLabel) and the breadcrumb (packages/app-shell/src/layout/AppHeader.tsx about :444). If the trace lands in packages/i18n/src/useObjectLabel.ts, that file is in seat 2's objectui#11201 claim (5921933038, a comment-only edit). The dev reports it, waits for that PR to land, then merges main.
Their pins, and one .changeset/11295-*.md per released package changed.
⛔ No second translation pass over a served value. ⛔ No copy of the server's override rule in the client. ⛔ Not packages/layout (objectui#11201, seat 2). The dev stops on a breach and explains it in the report.
Container & model: M, mode:subagent, model: opus (default judgment tier; dispatch-gates.mjs --tier answers no path-derived mandate for objectui paths)
Clause-②: yes
Thread-read: none
Serial constraints cleared: read 2026-10-01T00:08Z at objectui origin/maine2271568f8. No open PR names plugin-dashboard, ObjectView.tsx, AppHeader.tsx, useObjectLabel.ts or useNavTargetLabel.ts (9 open PRs scanned). The one live claim naming the label path is objectui#11201 (seat 2, packages/layout plus a comment in useObjectLabel.ts), handled above. No other area:i18n card is in flight.
Scope: the card's direction and pins as filed (triage, objectstack seat post objectstack-ai/objectstack#6015). A served document is not translated twice. PR says Fixes #11295. Clause-②: yes — why: a published renderer (@object-ui/plugin-dashboard) changes what it draws for a served document. Telling a served document from an inline one may need a prop or context the dev measures, and the ACCEPT re-reads any export it touches.
os-dev-report
{
"issue": 11295,
"status": "done",
"branch": "claude/issue-11295-served-title-not-retranslated",
"pr": "#11303",
"session": "session_0122Knsowci76D2rBWReCzzZ",
"premise_still_valid": true,
"summary": "A served dashboard and a served list view are now drawn as served. plugin-dashboard: DashboardRenderer gains a localized prop. With it, the widget title, description and sub-caption, and the renderer's own header label and description, skip the client bundle lookup. Inline maps are still collapsed, and header-action labels keep their lookup because the server does not translate them. useWidgetSubCaption takes the same flag. app-shell: DashboardView sets localized and draws its page header (label, description) as given. A new hooks/useServedViewItems.ts answers, by identity, whether the /meta/view read served a view. ObjectView (desktop tabs, mobile switcher, record way-back label) and the AppHeader breadcrumb draw a served view's label as given; every other view keeps viewLabel. The breadcrumb now matches the URL's view with resolveViewId, so a bare /view/in_progress finds the qualified served view instead of drawing the humanized slug. That slug was the measured en reading; the zh-CN reading was the bundle. The AppHeader dashboard crumb draws a served dashboard's label as given. Signal, Zone 2 item 2: none existed. The served document carries no marker, and a provider-wide context would cover inline and preview documents too. So it is one host prop for the dashboard, set where the /meta document is handed over (DashboardView), plus /meta/view cache membership by name for views. Views need a per-view answer because objectstack origin/main 5f6b63a6fd translateObject does not translate an object's embedded listViews: measured with the published spec 17.5.0 translator, zh-CN left listViews.mine.label as My Links while it translated the object and view-item labels. Those tabs keep the bundle, their only translation. The sub-caption and description channels had the same defect and are fixed (Zone 2 item 5). The fix touches neither packages/i18n/src/useObjectLabel.ts nor packages/layout. Beyond the card's named sites, two things are in scope by the card's direction: the dashboard's own label and description (page header, renderer header, breadcrumb) and the way-back label. Both are named in the PR body.",
"tests": "All heavy runs went through os-verify-lock (slot issue-11295). RED FIRST at base e3782d2 (tests only): pnpm exec vitest run packages/plugin-dashboard/src/__tests__/DashboardRenderer.servedLocalized-11295.test.tsx gave Tests 2 failed | 4 passed (6). The 2 red are the en and zh-CN published-edit cells (Unable to find an element with the text: Operations board (edited-11295)); the unedited and inline-control cells were green. REVERSE VERIFICATION after commit 80ae625: the 5 implementation files were checked out from base e3782d26ec in a trap-guarded script. Proof on disk: occurrence counts of localized/servedViews were 0 in DashboardRenderer.tsx, widgetSubCaption.ts, DashboardView.tsx, ObjectView.tsx and AppHeader.tsx. The 4 pin files then gave Test Files 4 failed (4) / Tests 12 failed | 14 passed (26), the predicted split: 2 dashboard, 2 DashboardView, 6 AppHeader (bare URL, qualified URL and dashboard crumb x en and zh-CN), 2 ObjectView. Every unedited and control cell stayed green. Restore was git checkout HEAD -- on absolute paths; git diff HEAD was empty and all 5 blob hashes equal HEAD. objectui has no scripts/ablation-replace.mjs, so the mutation was landed by checkout and proven by grep -c. The pins resolve @object-ui/* to src through the vitest aliases, so no dist is involved. CROSS-PACKAGE TYPE REVERSE: in DashboardView, localized was swapped for localizedTypo11295 (python replace with count==1 assert; on disk injected=1, original=0). npx tsc --noEmit in packages/app-shell then exited 2 with TS2322 ... is not assignable to type 'IntrinsicAttributes & DashboardRendererProps & RefAttributes HTMLDivElement'. Restored, blob equals HEAD. BUILD: pnpm --workspace-concurrency=2 --filter '@object-ui/app-shell^...' build gave VERDICT command-exit 0 (137s, shared box); dist/DashboardRenderer.d.ts and dist/widgetSubCaption.d.ts carry localized?: boolean. TYPE-CHECK: pnpm --filter @object-ui/plugin-dashboard type-check && pnpm --filter @object-ui/app-shell type-check gave VERDICT command-exit 0. Both scripts echoed, and both chain tsconfig.test.json, so the new tests compile. It was re-run for app-shell after the last source edit, exit 0. SUITES: pnpm exec vitest run --maxWorkers=2 packages/plugin-dashboard/ at 27fa9a0 gave Test Files 156 passed (156) / Tests 1426 passed | 6 skipped (1432). The only later commit, 5c84eb4, touches packages/app-shell/src/views/ObjectView.tsx alone, which plugin-dashboard cannot import. The union at the final head 5c84eb4 gave Test Files 118 passed (118) / Tests 1564 passed (1564), exit 0. It covered: the dashboard pin; packages/app-shell/src/views/ObjectView*, DashboardView* and layout/; every suite git grep -l finds for tWidgetTitle, widgetTitle(, viewLabel( or useWidgetSubCaption; and every test that reads a touched file by path (apps/console x3, examples/schema-catalog plugin-dashboard-gallery-render, collaboration, data-objectstack, plugin-grid, plugin-view, sdui-parser, types x2, i18n x2, scripts/tests x4). LINT, narrowed and proven at 5c84eb4: (1) population read from eslint.config.js: rule objects scoped **/*.{ts,tsx}, which holds all 10 changed TS files; (2) eslint --format json gave files 10, errors 0, and the warnings per file per rule equal the base versions of the same files read with the same config (ObjectView exhaustive-deps 9 = 9 after the 5c84eb4 fix; AppHeader 22 = 22; DashboardView 9 = 9; DashboardRenderer 6 = 6; widgetSubCaption 0 = 0); (3) invariance: 0 hits for parserOptions/projectService in eslint.config.js, so there is no type-aware linting and untouched files cannot move. The repo-wide pnpm lint is CI's.",
"mcp_calls": "0",
"api_writes": "3 REST writes, each ONE fleet-write relay repository_dispatch (POST /repos/objectstack-ai/objectstack/dispatches) executed as objectstack-fleet[bot]: (1) pr_create → POST /repos/objectstack-ai/objectui/pulls (draft #11303, run 36799389573 success; body read back byte-identical, 10918 bytes, first differing byte: none); (2) label-write --assign os-warren → POST /repos//issues/11303/assignees (run 36799453539 success, read back MATCHES; no label written; the PR carries documentation, plugin, tests, package: app-shell set by the labeler); (3) this os-dev-report comment → POST /repos//issues/11295/comments. Plus git push (not REST): the empty-branch probe and 3 pushes. Reads were unauthenticated-proxy REST GETs.",
"gates": "At 5c84eb4 unless noted, every command exit 0 with its own verdict line: node scripts/check-changeset-presence.mjs (10 source files of 2 released packages, 2 changesets declared); pnpm changeset:check (No changeset declares a major bump); pnpm check:new-line-citations (VERDICT new-cross-file-line-citations: 0 new citation(s), enforcement report-only → exit 0); pnpm check:control-bytes (OK, 9751 tracked text files); pnpm check:doc-fences; node scripts/check-doc-links.mjs (Links are valid across 17 scan roots); check:vi-mock-specifiers, check:vi-mock-inherit, check:vi-mock-override-shape, check:test-path-roots, check:unreferenced-sources, check:changeset-claims, check:pending-changeset-literals, check:phantom-deps, check:self-import (all OK); node scripts/check-governed-queue-guard.mjs --test over the 14 paths (NOT GOVERNED). NOT MEASURED: check:doc-snippets, reason PREREQUISITE NOT MET (it needs 34 built packages; this run built the 29-package app-shell closure), and the docs edits are prose with no code fence added. NOT MEASURED: check:readme-exports, same prerequisite reason; no README fence or export changed. CI at report time, one read, not polled: 42 check runs (total_count 42 = array 42): 20 success, 3 skipped, 19 in_progress, 0 failure. Status: in_progress.",
"line_budget": "not applicable: no skills/** file or line-ratcheted ledger touched. Diff +1218 / -36 over 14 files (5 source, 4 tests, 2 changesets, 1 new hook, README, docs mdx).",
"files_changed": [
"packages/plugin-dashboard/src/DashboardRenderer.tsx (+41 / -9)",
"packages/plugin-dashboard/src/widgetSubCaption.ts (+18 / -9)",
"packages/plugin-dashboard/src/tests/DashboardRenderer.servedLocalized-11295.test.tsx (+203, new)",
"packages/plugin-dashboard/README.md (+22)",
"packages/app-shell/src/hooks/useServedViewItems.ts (+77, new)",
"packages/app-shell/src/views/ObjectView.tsx (+50 / -8)",
"packages/app-shell/src/views/DashboardView.tsx (+14 / -8)",
"packages/app-shell/src/layout/AppHeader.tsx (+23 / -4)",
"packages/app-shell/src/views/DashboardView.servedLocalized-11295.test.tsx (+179, new)",
"packages/app-shell/src/views/ObjectView.servedViewLabel-11295.test.tsx (+234, new)",
"packages/app-shell/src/layout/tests/AppHeader.servedLabels-11295.test.tsx (+283, new)",
"content/docs/plugins/plugin-dashboard.mdx (+15)",
".changeset/11295-dashboard-served-localized.md (+29, new, patch @object-ui/plugin-dashboard)",
".changeset/11295-app-shell-served-labels.md (+28, new, patch @object-ui/app-shell)"
],
"deviations": [
"Scope, named in the PR body. Beyond the widget title, description and sub-caption, the view tab and the breadcrumb, the fix also draws the SAME served dashboard's own label and description as given: the DashboardView page header, DashboardRenderer's own header when shown, and the AppHeader dashboard crumb. It also routes the record page's way-back label and the mobile view switcher through the tab's helper. The card's direction reads 'the renderer draws the served title and description as given'; the dashboard's title is its label.",
"The breadcrumb now matches the URL's view with resolveViewId instead of a direct key lookup. Without it, the measured en breadcrumb drew the humanized slug for a bare /view/in_progress whatever was served, so the pin could not hold.",
"File surface: packages/app-shell/src/hooks/useServedViewItems.ts is new. It is the view signal's one module, the setting point the order allows. packages/plugin-dashboard/README.md and content/docs/plugins/plugin-dashboard.mdx were edited per AGENTS.md section 5 rule #2 (docs-driven): prose only, no code fence.",
"Gates: the build command gained --workspace-concurrency=2, placed before --filter, per the resource rules.",
"Gates: the full plugin-dashboard suite ran at 27fa9a0, not at the final head. The final commit 5c84eb4 touches only app-shell ObjectView.tsx. The app-shell union, the 4 pins and the repo checks were re-run at 5c84eb4.",
"Ablation tooling: objectui has neither scripts/ablation-replace.mjs nor ablation-dist-preflight.mjs. The revert leg used git checkout BASE -- on the 5 paths, proven by grep -c; the type reverse used a python replace that asserts its anchor count == 1, proven by grep -c. Both had a trap restore, blob == HEAD, and an empty git diff HEAD. The test pins resolve src through the vitest aliases, so no dist was in play.",
"Attribution: the commits end with AGENTS.md's model-free trailer pair (Claude-Session + Co-authored-by: Claude), not the harness's model-named Co-Authored-By. The PR body ends with os-dev.md's session-URL footer, not the harness's form. Both follow the precedence rule.",
"main moved 4 commits past base (d79f525), none on these files, useObjectLabel.ts or MetadataProvider.tsx. The branch was not merged.",
"Cleanup ran before this comment, because the write tools run from /home/user/objectstack: node_modules removed, then git worktree remove without --force, exit 0. Nothing was left uncommitted: the remote head equals the local 5c84eb4."
],
"open_questions": [],
"out_of_scope_findings": [
"class: b · reach: named producer: platform-objects sys_account.object.ts embeds listViews.mine (label My Links), and its _views catalog ships in en.objects.generated.ts. The /meta/object HTTP door is NOT MEASURED · evidence: at objectstack origin/main 5f6b63a6fd, translateObject (packages/spec/src/system/i18n-resolver.ts) has no listViews read, while os i18n extract (packages/cli/src/utils/i18n-extract.ts) writes _views keys for obj.listViews. The published @objectstack/spec 17.5.0 translateMetadataDocument('object', …) under zh-CN left listViews.mine.label = My Links and translated the object label to 账户. Contract quoted: translateView's docblock, 'Useful for translating metadata at the API boundary so any client (Studio, app-shell, plain HTTP) receives already-localized labels'. That statement is the VIEW translator's; the seat judges whether it binds the object-embedded channel. Consequence: a non-console client gets the authored text for those tabs, and the console's bundle is their only translation. This PR keeps it deliberately · Seam: spec:translateObject (objects[].listViews.*.label) → runtime:translateMetaDocument on /meta/object | renderer:app-shell ObjectView tab + AppHeader crumb · dedupe words: translateObject listViews, object embedded listViews untranslated, _views catalog object document, meta/object listViews label locale, sys_account My Links",
"carrier: 承接者:无 · noted, not filed. Nav entries with an absent label inherit their target's label through a second bundle pass over the served view or dashboard label (useNavTargetLabel, UnifiedSidebar, nav-menu-renderer call viewLabel/dashboardLabel with the served text as fallback). This is the same class as this card. Not measured. The nav label path is objectui#11201's area (seat 2), which is in flight on NavigationRenderer, not on these files.",
"carrier: 承接者:无 · noted, not filed. objectLabel(objectDef) re-resolves a served object label through the bundle, while the server keeps an explicit object label edit (objectstack #8284 rule). Same class, not measured, broad surface.",
"carrier: 承接者:无 · noted, not filed. The AppHeader page and report crumbs pass through the bundle the same way. Today the server has no packaged-base override rule for those types (PACKAGED_BASE_ACCESSORS = object, dashboard, view), so nothing differs visibly yet."
]
}
os-dev-report
{
"issue": 11295,
"round": "patch round 1",
"status": "done",
"branch": "claude/issue-11295-served-title-not-retranslated",
"pr": "#11303",
"session": "session_0122Knsowci76D2rBWReCzzZ",
"premise_still_valid": true,
"summary": "Patch round 1, the seat's ruling on contract review 5922835154 (PASS on 5c84eb4): .changeset/11295-dashboard-served-localized.md moves @object-ui/plugin-dashboard from patch to minor. The reason is that DashboardRenderer gains the public localized prop, and useWidgetSubCaption the same flag. Only the bump line changed. The first prose line starts fix(plugin-dashboard): … and never said patch, so it is unchanged. @object-ui/app-shell stays patch. The worktree was recreated from the branch at 5c84eb4, and the remote head was confirmed equal before the edit. One commit, 2d563c1, was pushed. main was not merged. The PR body is not edited (dev writes it once). One line there is now stale: 'There is one patch changeset per released package.' It should read 'There is one changeset per released package: minor for @object-ui/plugin-dashboard, patch for @object-ui/app-shell.' The seat writes that if wanted.",
"tests": "No source changed, so no test or build was owed. At 2d563c1 (the edit was checked before the commit, on a tree byte-identical to it): pnpm changeset:check exit 0 (✅ All workspace packages are in the changeset fixed group. / ✅ No changeset declares a \\major\ bump.); node scripts/check-changeset-presence.mjs exit 0 (✅ 10 source file(s) of 2 released package(s) changed, and this change declares 2 changeset(s)); pnpm check:changeset-claims exit 0; pnpm check:control-bytes exit 0 (OK, 9751 tracked text files). Diff vs 5c84eb4: 1 file, +1 / -1.",
"mcp_calls": "0",
"api_writes": "1 REST write this round: this os-dev-report comment → POST /repos//issues/11295/comments, via ONE fleet-write relay repository_dispatch (POST /repos/objectstack-ai/objectstack/dispatches) executed as objectstack-fleet[bot]. Plus 1 git push (not REST): 5c84eb4..2d563c1. No PR body, label or assignee write.",
"gates": "changeset:check exit 0; check-changeset-presence exit 0; check:changeset-claims exit 0; check:control-bytes exit 0, all at 2d563c1. CI on 2d563c1: not read (just pushed); convergence is the seat's.",
"line_budget": "not applicable: no skills/** file or ledger touched.",
"files_changed": [
".changeset/11295-dashboard-served-localized.md (+1 / -1: '@object-ui/plugin-dashboard': patch → minor)"
],
"deviations": [
"The PR body line 'There is one patch changeset per released package.' is now stale and is left as written. The suggested text is in summary.",
"Worktree: recreated with git worktree add on the existing local branch, after confirming the local branch, the fetched remote head and the starting HEAD all equal 5c84eb4. No pnpm install: the changeset checks are plain node scripts. Removed after this comment with git worktree remove (no --force)."
],
"open_questions": [],
"out_of_scope_findings": []
}
✅ ACCEPT: PR objectui#11303 at 2d563c1f6; ready and auto-merge follow this ACCEPT
domain:ui seat 1 · session_0122Knsowci76D2rBWReCzzZ · 2026-10-01T01:41Z. Checked against the diff and the head's check-runs. Claim 5921983728; dev reports 5922666442 and patch round 1 5922859065.
Contract review at CONTRACT_REVIEW_TIER:
Round 1 5922835154 on 5c84eb4b5 was PASS, with one non-blocking semver note: a new public prop on a published renderer reads as minor.
The seat ruled minor. Patch round 1 changed exactly that line.
The delta record 5922963935 is PASS on this head, which is the landing head. Round 1's judgments carry over.
the card's direction: a served document is not translated twice
the dashboard path: one host prop, localized?: boolean on DashboardRenderer (and useWidgetSubCaption), set only by app-shell's DashboardView, where the /meta document is handed over. With it, the widget title, description and sub-caption, and the dashboard's own label and description, skip the bundle. Header-action labels keep their lookup, because the server does not translate them. Inline maps are still collapsed. Preview and inline hosts leave it unset
the view path
useServedViewItems answers, by identity, whether the /meta/view read served a view. Only those labels are drawn as given: the desktop tabs, the mobile switcher, the record way-back label and the AppHeader crumb. An object's embedded listViews keep the bundle, because the server does not translate them (measured at objectstack origin/main; now objectstack-ai/objectstack#21006)
prohibitions
no second translation pass over a served value, no copy of the server's override rule, no string comparison, nothing in packages/layout or useObjectLabel.ts
the breadcrumb matcher
it now resolves the URL's view through resolveViewId. At base, a bare /view/in_progress missed the qualified view and drew a humanized slug
pins
the card's four, through the real components in en and zh-CN: a served edit drawn as served, an unedited widget still translated, the inline control, and the view tab and crumb. Red-first 2 of 6 at base; reversing the 5 implementation files reddens 12 of 26 cells with every control green
semver
@object-ui/plugin-dashboardminor (a new public prop) and @object-ui/app-shell patch. Clause-②: yes (the claim). The PR body's line "There is one patch changeset per released package" predates the patch round: the changesets are the release's source, and they are right
5 commits on main since e3782d26ec, none touching this PR's 14 files. A test merge onto current main (1ccb5ba7de) is clean, and the merge queue re-tests the merged tree
scope / governed
14 files, +1218 / −36; check-governed-merges.mjs: not governed. Fixes #11295
Three more sites of this card's class: nav entries inheriting a served label, objectLabel(objectDef), and the page / report crumbs. They re-resolve a served label through the bundle, but none is measured, and the server has no override rule for pages or reports yet → Acceptance notes. One closure card follows on the first measured reach.
A name-only collision in isServedView is theoretical for every producer in the repo → Acceptance notes.
Next: objectui#4044 (DashboardWidget.chartConfig, the same DashboardRenderer.tsx) waited on this card.
PR objectui#11303 (Fixes #11295) merged through the merge queue as b28bde8a4b, which is on origin/main. The merge closed the card by its Fixes keyword. The seat removes the pm:dispatched state label and the assignee in the same pass.
It merged at 2026-10-01T01:57:09Z. Verified by content: all 14 of its files on origin/main are blob-identical to the landing head 2d563c1f6.
What ships: a served dashboard and a served list view are drawn as served. DashboardRenderer takes a localized prop that app-shell's DashboardView sets for the /meta document, so its widget titles, descriptions, sub-captions and its own label skip the packaged bundle. A view the /meta/view read served shows its label as given on the tabs, the mobile switcher, the way-back label and the breadcrumb. Inline and preview documents keep the bundle composition. The records are 5922835154 and the delta 5922963935 (at-tier PASS on the landing head), and the ACCEPT is 5923016925.
What stays, as Acceptance notes (no measured reach, not filed): the nav-entry label inheritance, objectLabel(objectDef) and the page / report crumbs re-resolve a served label through the bundle (the same class); a name-only collision in isServedView is theoretical.
Unblocked: objectui#4044 (DashboardWidget.chartConfig, the same DashboardRenderer.tsx) waited on this card.
Activity
objectstack-fleet commentedon Oct 1, 2026
Claim: PM loop round 1
Session:
session_0122Knsowci76D2rBWReCzzZAccount:
os-warren(the seat's linked user asGET /useranswers it; the card's assignee)Branch:
claude/issue-11295-served-title-not-retranslatedWorktree:
objectui-issue-11295Domain:
domain:uiSeat:
domain:ui#1File surface:
packages/plugin-dashboard/src/DashboardRenderer.tsx,tWidgetTitle/tWidgetDescription(about:412/:421), and the sub-caption channel if it has the same shape. A served dashboard's title and description are drawn as given. The bundle composition stays for documents the server did not translate (inline and preview).packages/app-shell/src/views/ObjectView.tsxabout:2079,viewLabel) and the breadcrumb (packages/app-shell/src/layout/AppHeader.tsxabout:444). If the trace lands inpackages/i18n/src/useObjectLabel.ts, that file is in seat 2's objectui#11201 claim (5921933038, a comment-only edit). The dev reports it, waits for that PR to land, then mergesmain..changeset/11295-*.mdper released package changed.⛔ No second translation pass over a served value. ⛔ No copy of the server's override rule in the client. ⛔ Not
packages/layout(objectui#11201, seat 2). The dev stops on a breach and explains it in the report.Container & model:
M,mode:subagent,model: opus(default judgment tier;dispatch-gates.mjs --tieranswers no path-derived mandate for objectui paths)Clause-②: yes
Thread-read: none
Serial constraints cleared: read 2026-10-01T00:08Z at objectui
origin/maine2271568f8. No open PR namesplugin-dashboard,ObjectView.tsx,AppHeader.tsx,useObjectLabel.tsoruseNavTargetLabel.ts(9 open PRs scanned). The one live claim naming the label path is objectui#11201 (seat 2,packages/layoutplus a comment inuseObjectLabel.ts), handled above. No otherarea:i18ncard is in flight.Scope: the card's direction and pins as filed (triage, objectstack seat post objectstack-ai/objectstack#6015). A served document is not translated twice. PR says
Fixes #11295.Clause-②: yes— why: a published renderer (@object-ui/plugin-dashboard) changes what it draws for a served document. Telling a served document from an inline one may need a prop or context the dev measures, and the ACCEPT re-reads any export it touches.domain:uiseat 1 · claim · 2026-10-01T00:08ZGenerated by Claude Code
objectstack-fleet commentedon Oct 1, 2026
os-dev-report
{
"issue": 11295,
"status": "done",
"branch": "claude/issue-11295-served-title-not-retranslated",
"pr": "#11303",
"session": "session_0122Knsowci76D2rBWReCzzZ",
"premise_still_valid": true,
"summary": "A served dashboard and a served list view are now drawn as served. plugin-dashboard: DashboardRenderer gains a
localizedprop. With it, the widget title, description and sub-caption, and the renderer's own header label and description, skip the client bundle lookup. Inline maps are still collapsed, and header-action labels keep their lookup because the server does not translate them. useWidgetSubCaption takes the same flag. app-shell: DashboardView setslocalizedand draws its page header (label, description) as given. A new hooks/useServedViewItems.ts answers, by identity, whether the /meta/view read served a view. ObjectView (desktop tabs, mobile switcher, record way-back label) and the AppHeader breadcrumb draw a served view's label as given; every other view keepsviewLabel. The breadcrumb now matches the URL's view with resolveViewId, so a bare /view/in_progress finds the qualified served view instead of drawing the humanized slug. That slug was the measuredenreading; thezh-CNreading was the bundle. The AppHeader dashboard crumb draws a served dashboard's label as given. Signal, Zone 2 item 2: none existed. The served document carries no marker, and a provider-wide context would cover inline and preview documents too. So it is one host prop for the dashboard, set where the /meta document is handed over (DashboardView), plus /meta/view cache membership by name for views. Views need a per-view answer because objectstack origin/main 5f6b63a6fd translateObject does not translate an object's embedded listViews: measured with the published spec 17.5.0 translator, zh-CN left listViews.mine.label asMy Linkswhile it translated the object and view-item labels. Those tabs keep the bundle, their only translation. The sub-caption and description channels had the same defect and are fixed (Zone 2 item 5). The fix touches neither packages/i18n/src/useObjectLabel.ts nor packages/layout. Beyond the card's named sites, two things are in scope by the card's direction: the dashboard's own label and description (page header, renderer header, breadcrumb) and the way-back label. Both are named in the PR body.","tests": "All heavy runs went through os-verify-lock (slot issue-11295). RED FIRST at base e3782d2 (tests only):
pnpm exec vitest run packages/plugin-dashboard/src/__tests__/DashboardRenderer.servedLocalized-11295.test.tsxgaveTests 2 failed | 4 passed (6). The 2 red are the en and zh-CN published-edit cells (Unable to find an element with the text: Operations board (edited-11295)); the unedited and inline-control cells were green. REVERSE VERIFICATION after commit 80ae625: the 5 implementation files were checked out from basee3782d26ecin a trap-guarded script. Proof on disk: occurrence counts of localized/servedViews were 0 in DashboardRenderer.tsx, widgetSubCaption.ts, DashboardView.tsx, ObjectView.tsx and AppHeader.tsx. The 4 pin files then gaveTest Files 4 failed (4) / Tests 12 failed | 14 passed (26), the predicted split: 2 dashboard, 2 DashboardView, 6 AppHeader (bare URL, qualified URL and dashboard crumb x en and zh-CN), 2 ObjectView. Every unedited and control cell stayed green. Restore wasgit checkout HEAD --on absolute paths;git diff HEADwas empty and all 5 blob hashes equal HEAD. objectui has no scripts/ablation-replace.mjs, so the mutation was landed by checkout and proven by grep -c. The pins resolve @object-ui/* to src through the vitest aliases, so no dist is involved. CROSS-PACKAGE TYPE REVERSE: in DashboardView,localizedwas swapped forlocalizedTypo11295(python replace with count==1 assert; on disk injected=1, original=0).npx tsc --noEmitin packages/app-shell then exited 2 withTS2322 ... is not assignable to type 'IntrinsicAttributes & DashboardRendererProps & RefAttributes HTMLDivElement'. Restored, blob equals HEAD. BUILD:pnpm --workspace-concurrency=2 --filter '@object-ui/app-shell^...' buildgaveVERDICT command-exit 0(137s, shared box); dist/DashboardRenderer.d.ts and dist/widgetSubCaption.d.ts carrylocalized?: boolean. TYPE-CHECK:pnpm --filter @object-ui/plugin-dashboard type-check && pnpm --filter @object-ui/app-shell type-checkgaveVERDICT command-exit 0. Both scripts echoed, and both chain tsconfig.test.json, so the new tests compile. It was re-run for app-shell after the last source edit, exit 0. SUITES:pnpm exec vitest run --maxWorkers=2 packages/plugin-dashboard/at 27fa9a0 gaveTest Files 156 passed (156) / Tests 1426 passed | 6 skipped (1432). The only later commit, 5c84eb4, touches packages/app-shell/src/views/ObjectView.tsx alone, which plugin-dashboard cannot import. The union at the final head 5c84eb4 gaveTest Files 118 passed (118) / Tests 1564 passed (1564), exit 0. It covered: the dashboard pin; packages/app-shell/src/views/ObjectView*, DashboardView* and layout/; every suitegit grep -lfinds for tWidgetTitle, widgetTitle(, viewLabel( or useWidgetSubCaption; and every test that reads a touched file by path (apps/console x3, examples/schema-catalog plugin-dashboard-gallery-render, collaboration, data-objectstack, plugin-grid, plugin-view, sdui-parser, types x2, i18n x2, scripts/tests x4). LINT, narrowed and proven at 5c84eb4: (1) population read from eslint.config.js: rule objects scoped**/*.{ts,tsx}, which holds all 10 changed TS files; (2)eslint --format jsongave files 10, errors 0, and the warnings per file per rule equal the base versions of the same files read with the same config (ObjectView exhaustive-deps 9 = 9 after the 5c84eb4 fix; AppHeader 22 = 22; DashboardView 9 = 9; DashboardRenderer 6 = 6; widgetSubCaption 0 = 0); (3) invariance: 0 hits for parserOptions/projectService in eslint.config.js, so there is no type-aware linting and untouched files cannot move. The repo-widepnpm lintis CI's.","mcp_calls": "0",
"api_writes": "3 REST writes, each ONE fleet-write relay repository_dispatch (POST /repos/objectstack-ai/objectstack/dispatches) executed as objectstack-fleet[bot]: (1) pr_create → POST /repos/objectstack-ai/objectui/pulls (draft #11303, run 36799389573 success; body read back byte-identical, 10918 bytes, first differing byte: none); (2) label-write --assign os-warren → POST /repos//issues/11303/assignees (run 36799453539 success, read back MATCHES; no label written; the PR carries documentation, plugin, tests, package: app-shell set by the labeler); (3) this os-dev-report comment → POST /repos//issues/11295/comments. Plus git push (not REST): the empty-branch probe and 3 pushes. Reads were unauthenticated-proxy REST GETs.",
"gates": "At 5c84eb4 unless noted, every command exit 0 with its own verdict line:
node scripts/check-changeset-presence.mjs(10 source files of 2 released packages, 2 changesets declared);pnpm changeset:check(No changeset declares amajorbump);pnpm check:new-line-citations(VERDICT new-cross-file-line-citations: 0 new citation(s), enforcement report-only → exit 0);pnpm check:control-bytes(OK, 9751 tracked text files);pnpm check:doc-fences;node scripts/check-doc-links.mjs(Links are valid across 17 scan roots);check:vi-mock-specifiers,check:vi-mock-inherit,check:vi-mock-override-shape,check:test-path-roots,check:unreferenced-sources,check:changeset-claims,check:pending-changeset-literals,check:phantom-deps,check:self-import(all OK);node scripts/check-governed-queue-guard.mjs --testover the 14 paths (NOT GOVERNED). NOT MEASURED: check:doc-snippets, reason PREREQUISITE NOT MET (it needs 34 built packages; this run built the 29-package app-shell closure), and the docs edits are prose with no code fence added. NOT MEASURED: check:readme-exports, same prerequisite reason; no README fence or export changed. CI at report time, one read, not polled: 42 check runs (total_count 42 = array 42): 20 success, 3 skipped, 19 in_progress, 0 failure. Status: in_progress.","line_budget": "not applicable: no skills/** file or line-ratcheted ledger touched. Diff +1218 / -36 over 14 files (5 source, 4 tests, 2 changesets, 1 new hook, README, docs mdx).",
"files_changed": [
"packages/plugin-dashboard/src/DashboardRenderer.tsx (+41 / -9)",
"packages/plugin-dashboard/src/widgetSubCaption.ts (+18 / -9)",
"packages/plugin-dashboard/src/tests/DashboardRenderer.servedLocalized-11295.test.tsx (+203, new)",
"packages/plugin-dashboard/README.md (+22)",
"packages/app-shell/src/hooks/useServedViewItems.ts (+77, new)",
"packages/app-shell/src/views/ObjectView.tsx (+50 / -8)",
"packages/app-shell/src/views/DashboardView.tsx (+14 / -8)",
"packages/app-shell/src/layout/AppHeader.tsx (+23 / -4)",
"packages/app-shell/src/views/DashboardView.servedLocalized-11295.test.tsx (+179, new)",
"packages/app-shell/src/views/ObjectView.servedViewLabel-11295.test.tsx (+234, new)",
"packages/app-shell/src/layout/tests/AppHeader.servedLabels-11295.test.tsx (+283, new)",
"content/docs/plugins/plugin-dashboard.mdx (+15)",
".changeset/11295-dashboard-served-localized.md (+29, new, patch @object-ui/plugin-dashboard)",
".changeset/11295-app-shell-served-labels.md (+28, new, patch @object-ui/app-shell)"
],
"deviations": [
"Scope, named in the PR body. Beyond the widget title, description and sub-caption, the view tab and the breadcrumb, the fix also draws the SAME served dashboard's own label and description as given: the DashboardView page header, DashboardRenderer's own header when shown, and the AppHeader dashboard crumb. It also routes the record page's way-back label and the mobile view switcher through the tab's helper. The card's direction reads 'the renderer draws the served title and description as given'; the dashboard's title is its label.",
"The breadcrumb now matches the URL's view with resolveViewId instead of a direct key lookup. Without it, the measured en breadcrumb drew the humanized slug for a bare /view/in_progress whatever was served, so the pin could not hold.",
"File surface: packages/app-shell/src/hooks/useServedViewItems.ts is new. It is the view signal's one module, the setting point the order allows. packages/plugin-dashboard/README.md and content/docs/plugins/plugin-dashboard.mdx were edited per AGENTS.md section 5 rule #2 (docs-driven): prose only, no code fence.",
"Gates: the build command gained --workspace-concurrency=2, placed before --filter, per the resource rules.",
"Gates: the full plugin-dashboard suite ran at 27fa9a0, not at the final head. The final commit 5c84eb4 touches only app-shell ObjectView.tsx. The app-shell union, the 4 pins and the repo checks were re-run at 5c84eb4.",
"Ablation tooling: objectui has neither scripts/ablation-replace.mjs nor ablation-dist-preflight.mjs. The revert leg used
git checkout BASE --on the 5 paths, proven by grep -c; the type reverse used a python replace that asserts its anchor count == 1, proven by grep -c. Both had a trap restore, blob == HEAD, and an emptygit diff HEAD. The test pins resolve src through the vitest aliases, so no dist was in play.","Attribution: the commits end with AGENTS.md's model-free trailer pair (Claude-Session +
Co-authored-by: Claude), not the harness's model-named Co-Authored-By. The PR body ends with os-dev.md's session-URL footer, not the harness's form. Both follow the precedence rule.","main moved 4 commits past base (d79f525), none on these files, useObjectLabel.ts or MetadataProvider.tsx. The branch was not merged.",
"Cleanup ran before this comment, because the write tools run from /home/user/objectstack: node_modules removed, then
git worktree removewithout --force, exit 0. Nothing was left uncommitted: the remote head equals the local 5c84eb4."],
"open_questions": [],
"out_of_scope_findings": [
"class: b · reach: named producer: platform-objects
sys_account.object.tsembedslistViews.mine(labelMy Links), and its_viewscatalog ships inen.objects.generated.ts. The /meta/object HTTP door is NOT MEASURED · evidence: at objectstack origin/main 5f6b63a6fd,translateObject(packages/spec/src/system/i18n-resolver.ts) has nolistViewsread, whileos i18n extract(packages/cli/src/utils/i18n-extract.ts) writes_viewskeys forobj.listViews. The published @objectstack/spec 17.5.0translateMetadataDocument('object', …)under zh-CN leftlistViews.mine.label=My Linksand translated the object label to账户. Contract quoted: translateView's docblock, 'Useful for translating metadata at the API boundary so any client (Studio, app-shell, plain HTTP) receives already-localized labels'. That statement is the VIEW translator's; the seat judges whether it binds the object-embedded channel. Consequence: a non-console client gets the authored text for those tabs, and the console's bundle is their only translation. This PR keeps it deliberately · Seam: spec:translateObject (objects[].listViews.*.label) → runtime:translateMetaDocument on /meta/object | renderer:app-shell ObjectView tab + AppHeader crumb · dedupe words: translateObject listViews, object embedded listViews untranslated, _views catalog object document, meta/object listViews label locale, sys_account My Links","carrier: 承接者:无 · noted, not filed. Nav entries with an absent label inherit their target's label through a second bundle pass over the served view or dashboard label (
useNavTargetLabel,UnifiedSidebar,nav-menu-renderercall viewLabel/dashboardLabel with the served text as fallback). This is the same class as this card. Not measured. The nav label path is objectui#11201's area (seat 2), which is in flight on NavigationRenderer, not on these files.","carrier: 承接者:无 · noted, not filed.
objectLabel(objectDef)re-resolves a served object label through the bundle, while the server keeps an explicit object label edit (objectstack #8284 rule). Same class, not measured, broad surface.","carrier: 承接者:无 · noted, not filed. The AppHeader page and report crumbs pass through the bundle the same way. Today the server has no packaged-base override rule for those types (PACKAGED_BASE_ACCESSORS = object, dashboard, view), so nothing differs visibly yet."
]
}
Generated by Claude Code
objectstack-fleet commentedon Oct 1, 2026
os-dev-report
{
"issue": 11295,
"round": "patch round 1",
"status": "done",
"branch": "claude/issue-11295-served-title-not-retranslated",
"pr": "#11303",
"session": "session_0122Knsowci76D2rBWReCzzZ",
"premise_still_valid": true,
"summary": "Patch round 1, the seat's ruling on contract review 5922835154 (PASS on 5c84eb4):
.changeset/11295-dashboard-served-localized.mdmoves@object-ui/plugin-dashboardfrompatchtominor. The reason is that DashboardRenderer gains the publiclocalizedprop, and useWidgetSubCaption the same flag. Only the bump line changed. The first prose line startsfix(plugin-dashboard): …and never saidpatch, so it is unchanged.@object-ui/app-shellstayspatch. The worktree was recreated from the branch at 5c84eb4, and the remote head was confirmed equal before the edit. One commit, 2d563c1, was pushed. main was not merged. The PR body is not edited (dev writes it once). One line there is now stale: 'There is one patch changeset per released package.' It should read 'There is one changeset per released package: minor for@object-ui/plugin-dashboard, patch for@object-ui/app-shell.' The seat writes that if wanted.","tests": "No source changed, so no test or build was owed. At 2d563c1 (the edit was checked before the commit, on a tree byte-identical to it):
pnpm changeset:checkexit 0 (✅ All workspace packages are in the changeset fixed group./✅ No changeset declares a \\major\bump.);node scripts/check-changeset-presence.mjsexit 0 (✅ 10 source file(s) of 2 released package(s) changed, and this change declares 2 changeset(s));pnpm check:changeset-claimsexit 0;pnpm check:control-bytesexit 0 (OK, 9751 tracked text files). Diff vs 5c84eb4: 1 file, +1 / -1.","mcp_calls": "0",
"api_writes": "1 REST write this round: this os-dev-report comment → POST /repos//issues/11295/comments, via ONE fleet-write relay repository_dispatch (POST /repos/objectstack-ai/objectstack/dispatches) executed as objectstack-fleet[bot]. Plus 1 git push (not REST): 5c84eb4..2d563c1. No PR body, label or assignee write.",
"gates": "changeset:check exit 0; check-changeset-presence exit 0; check:changeset-claims exit 0; check:control-bytes exit 0, all at 2d563c1. CI on 2d563c1: not read (just pushed); convergence is the seat's.",
"line_budget": "not applicable: no skills/** file or ledger touched.",
"files_changed": [
".changeset/11295-dashboard-served-localized.md (+1 / -1:
'@object-ui/plugin-dashboard': patch→minor)"],
"deviations": [
"The PR body line 'There is one patch changeset per released package.' is now stale and is left as written. The suggested text is in summary.",
"Worktree: recreated with
git worktree addon the existing local branch, after confirming the local branch, the fetched remote head and the starting HEAD all equal 5c84eb4. Nopnpm install: the changeset checks are plain node scripts. Removed after this comment withgit worktree remove(no --force)."],
"open_questions": [],
"out_of_scope_findings": []
}
Generated by Claude Code
objectstack-fleet commentedon Oct 1, 2026
✅ ACCEPT: PR objectui#11303 at
2d563c1f6; ready and auto-merge follow this ACCEPTdomain:uiseat 1 ·session_0122Knsowci76D2rBWReCzzZ· 2026-10-01T01:41Z. Checked against the diff and the head's check-runs. Claim5921983728; dev reports5922666442and patch round 15922859065.CONTRACT_REVIEW_TIER:5922835154on5c84eb4b5was PASS, with one non-blocking semver note: a new public prop on a published renderer reads asminor.minor. Patch round 1 changed exactly that line.5922963935is PASS on this head, which is the landing head. Round 1's judgments carry over.Implemented-by: claude/issue-11295-served-title-not-retranslated,Reviewed-by: session_0122Knsowci76D2rBWReCzzZ.localized?: booleanonDashboardRenderer(anduseWidgetSubCaption), set only by app-shell'sDashboardView, where the/metadocument is handed over. With it, the widget title, description and sub-caption, and the dashboard's own label and description, skip the bundle. Header-action labels keep their lookup, because the server does not translate them. Inline maps are still collapsed. Preview and inline hosts leave it unsetuseServedViewItemsanswers, by identity, whether the/meta/viewread served a view. Only those labels are drawn as given: the desktop tabs, the mobile switcher, the record way-back label and theAppHeadercrumb. An object's embeddedlistViewskeep the bundle, because the server does not translate them (measured at objectstackorigin/main; now objectstack-ai/objectstack#21006)packages/layoutoruseObjectLabel.tsresolveViewId. At base, a bare/view/in_progressmissed the qualified view and drew a humanized slugenandzh-CN: a served edit drawn as served, an unedited widget still translated, the inline control, and the view tab and crumb. Red-first 2 of 6 at base; reversing the 5 implementation files reddens 12 of 26 cells with every control green@object-ui/plugin-dashboardminor (a new public prop) and@object-ui/app-shellpatch.Clause-②: yes(the claim). The PR body's line "There is one patch changeset per released package" predates the patch round: the changesets are the release's source, and they are right2d563c1f6: 43 runs, 40 success, 3 expected skips, 0 failuremainsincee3782d26ec, none touching this PR's 14 files. A test merge onto currentmain(1ccb5ba7de) is clean, and the merge queue re-tests the merged treecheck-governed-merges.mjs: not governed.Fixes #11295Out-of-scope findings:
translateObjectnever reads an object's embeddedlistViews, whileos i18n extractwrites_viewskeys for them (named producersys_account'slistViews.mine) → filed finding(spec,i18n):translateObjectnever reads an object's embeddedlistViews, so their labels are served in the authored language whileos i18n extractwrites_viewskeys for them objectstack#21006 (finding). If it lands, objectui'suseServedViewItemsalso counts/meta/object-embedded views as served.objectLabel(objectDef), and the page / report crumbs. They re-resolve a served label through the bundle, but none is measured, and the server has no override rule for pages or reports yet → Acceptance notes. One closure card follows on the first measured reach.name-only collision inisServedViewis theoretical for every producer in the repo → Acceptance notes.Next: objectui#4044 (
DashboardWidget.chartConfig, the sameDashboardRenderer.tsx) waited on this card.domain:uiseat 1 · ACCEPT · 2026-10-01T01:41ZGenerated by Claude Code
objectstack-fleet commentedon Oct 1, 2026
Landed: PR objectui#11303 merged as
b28bde8a4b; closedcompleteddomain:uiseat 1 ·session_0122Knsowci76D2rBWReCzzZ· 2026-10-01T02:05Z.Fixes #11295) merged through the merge queue asb28bde8a4b, which is onorigin/main. The merge closed the card by itsFixeskeyword. The seat removes thepm:dispatchedstate label and the assignee in the same pass.origin/mainare blob-identical to the landing head2d563c1f6.DashboardRenderertakes alocalizedprop that app-shell'sDashboardViewsets for the/metadocument, so its widget titles, descriptions, sub-captions and its own label skip the packaged bundle. A view the/meta/viewread served shows its label as given on the tabs, the mobile switcher, the way-back label and the breadcrumb. Inline and preview documents keep the bundle composition. The records are5922835154and the delta5922963935(at-tier PASS on the landing head), and the ACCEPT is5923016925..objectui-shacarriesb28bde8a4b, as the card's direction said.translateObjectnever reads an object's embeddedlistViews, so their labels are served in the authored language whileos i18n extractwrites_viewskeys for them objectstack#21006 (translateObjectnever reads an object's embeddedlistViews).objectLabel(objectDef)and the page / report crumbs re-resolve a served label through the bundle (the same class); aname-only collision inisServedViewis theoretical.DashboardWidget.chartConfig, the sameDashboardRenderer.tsx) waited on this card.domain:uiseat 1 · landed · 2026-10-01T02:05ZGenerated by Claude Code
test(app-shell): pin an embedded view's served label on the tab and t…
fix(plugin-dashboard,app-shell): a served dashboard and a served list…
fix(app-shell): count an object document's served listViews as served…