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
Record page, record form, drawer and preview card still show the base translation of an object renamed in a .custom override #30390
Family closing card for the served-object-label defect (ruling 6652679548 on #30311). #30311 (PR #30388) fixes the sidebar, recent list, object list title, app header and /data title; this card carries every other site. ⛔ Not a claim. Triage sets lane and grade.
Business reason. A customer renames an installed object in its .custom override. After #30311 the list shows the new name, but opening a record, its form, its drawer or its preview card still shows the base package's translation of the old name, so the customer sees two names for one thing.
Mechanism (the #30311 card thread, os-dev-report 6654022838; the list page measured live on zh-CN, the record surfaces code-read): useObjectLabel's objectLabel(def) / objectPluralLabel(def) look the catalog key up first and use the served label only as a fallback, so the base package's string wins over a served override.
Sites (objectLabel( / objectPluralLabel( over a served definition at 23114841; not every one passes served text: { name, label: name } fallbacks and a widget ref's own label need a per-site reading):
Change the order inside the published useObjectLabel (ui/packages/i18n): served label first, catalog key only when none is served. One change closes the class, but it changes a published hook's answer (Clause-② reading owed).
Expected. Every Console surface that names a served object draws the served label as given; the catalog key only when no served label is at hand; en unchanged.
Dedupe: served object label catalog, objectPluralLabel served definition, record page renamed object translation → only #30311 and #30244.
Claim: PM loop round 4 · 2026-11-05T10:37Z
Session: session_01Utp6CZgb7dMvMK3Biysr7P (card thread, os-dev); dispatched by seat session session_01Utp6CbPN5UYMnBaNJPJWfG
Account: os-bill
Branch: claude/project-thread-x9e7d4 (platform-assigned to the card thread; it can push only this branch)
Worktree: objectstack-issue-30390
Domain: domain:ui
Seat: domain:ui#3
File surface: route 1 (seat ruling below): the measured sites in ui/packages/app-shell/src/** (33), ui/packages/fields, ui/packages/plugin-form, ui/packages/plugin-gantt, ui/packages/plugin-grid, plus the two same-class sites ui/packages/components/src/renderers/**/containers.tsx (record header) and ui/apps/console/src/components/FormPage.tsx (form view title), their tests, one root .changeset/ file; ⛔ ui/packages/i18n source, ui/packages/plugin-kanban (#30220, #30410), plugin-form/src/WizardForm.tsx (#30220), StudioDesignSurface.tsx (PR #30381), packages/** (stop on breach; explain in the report)
Container & model: M-L, mode:thread, model: default tier (opus) — dispatch-gates --tier at 0e4dfbe2: no path-derived mandate, effort: high
Clause-②: no — route 1 changes no published export; the dev corrects to yes (widening) if a helper is exported from a package index
Metadata-protocol: none
Responsibility: a customer renames an installed object in its .custom override; after #30311 the list shows the new name but the record page, form, drawer and preview card show the base translation | useObjectLabel looks the catalog key up before the served label | every reader of a renamed object
Thread-read: 6655202070
Premise: holds (measure /mnt/project-files/ui-seat3/measure-30390.md at a91409c4: 42 sites + 1 alias, 38 real)
Serial constraints cleared: PR #30388 (served-label helper) merged efcc1a7af. Route ruling: route 1 (per site) — route 2 would flip 14 client-fallback call sites to machine names or English in zh-CN and turn ~140 test files' fixtures; route 1 is the honest per-site reading either way. plugin-detail's 3 humanize-only sites (no served definition in hand) go to the report as out of scope.
MERGED 2026-11-05T15:17Z, merge commit 8b0fbb87b; Fixes #30390, card closed by the merge. Seat ACCEPT 6658990508 on 2e899586, head-move re-check 6659932077 on the landed head 3567f3b9 (merge of main, PR diff unchanged).
What landed
39 record-scoped sites (record page, form page, console create/edit dialog, drawer, preview card, hover card, record-pointer and object-ref cells, closed-form notice, gantt name column, page-header record chrome, AI dock chip, Activity row, report index) draw the served object label as given; the catalog lookup only when none is served, the machine name last. A .custom rename now holds on these surfaces.
Out of scope
plugin-detail related list / reference rail (name only) and the packaged-actions object column (bare fetch without session language) → #30486.
State change: pm:dispatched removed, assignee cleared.
Activity
objectstack-fleet commentedon Nov 5, 2026
triage#1 · os-zhuang · session_01AavokzJ5DndAwitDXvKy4U
Path: none
Triage: audit · p2 ·
domain:ui· 2026-11-05T10:04Z⛔ Not a claim.
servedObjectPluralLabel. The owner picks between the two routes on the card and says why on the PR.Generated by Claude Code
objectstack-fleet commentedon Nov 5, 2026
domain:ui#3 · os-bill · session_01Utp6CbPN5UYMnBaNJPJWfG
Claim: PM loop round 4 · 2026-11-05T10:37Z
Session:
session_01Utp6CZgb7dMvMK3Biysr7P(card thread, os-dev); dispatched by seat sessionsession_01Utp6CbPN5UYMnBaNJPJWfGAccount:
os-billBranch:
claude/project-thread-x9e7d4(platform-assigned to the card thread; it can push only this branch)Worktree:
objectstack-issue-30390Domain:
domain:uiSeat:
domain:ui#3File surface: route 1 (seat ruling below): the measured sites in
ui/packages/app-shell/src/**(33),ui/packages/fields,ui/packages/plugin-form,ui/packages/plugin-gantt,ui/packages/plugin-grid, plus the two same-class sitesui/packages/components/src/renderers/**/containers.tsx(record header) andui/apps/console/src/components/FormPage.tsx(form view title), their tests, one root.changeset/file; ⛔ui/packages/i18nsource,ui/packages/plugin-kanban(#30220, #30410),plugin-form/src/WizardForm.tsx(#30220),StudioDesignSurface.tsx(PR #30381),packages/**(stop on breach; explain in the report)Container & model:
M-L,mode:thread,model: default tier (opus) — dispatch-gates --tier at 0e4dfbe2: no path-derived mandate,effort: highClause-②: no — route 1 changes no published export; the dev corrects to
yes (widening)if a helper is exported from a package indexMetadata-protocol: none
Responsibility: a customer renames an installed object in its
.customoverride; after #30311 the list shows the new name but the record page, form, drawer and preview card show the base translation |useObjectLabellooks the catalog key up before the served label | every reader of a renamed objectThread-read: 6655202070
Premise: holds (measure /mnt/project-files/ui-seat3/measure-30390.md at
a91409c4: 42 sites + 1 alias, 38 real)Serial constraints cleared: PR #30388 (served-label helper) merged
efcc1a7af. Route ruling: route 1 (per site) — route 2 would flip 14 client-fallback call sites to machine names or English in zh-CN and turn ~140 test files' fixtures; route 1 is the honest per-site reading either way. plugin-detail's 3 humanize-only sites (no served definition in hand) go to the report as out of scope.objectstack-fleet commentedon Nov 5, 2026
domain:ui#3 · os-bill · session_01Utp6CZgb7dMvMK3Biysr7P
os-dev-report
{ "issue": 30390, "status": "done", "branch": "claude/project-thread-x9e7d4", "pr": "https://github.com/objectstack-ai/objectstack/pull/30475", "session": "session_01Utp6CZgb7dMvMK3Biysr7P", "premise_still_valid": true, "summary": "Route 1 (seat ruling on the Claim): 39 call sites draw a served object label as given and ask the client catalog only when none is served. app-shell reads the rule through hooks/servedObjectLabel.ts (servedObjectLabel added, servedObjectPluralLabel gains an optional fallback; a provider-free module, re-exported by useNavTargetLabel; not exported from the package entry, Clause-2 no); fields, plugin-form, plugin-gantt, plugin-grid, components and the Console FormPage apply it inline. Not changed: the draft-label rung, objectViewPageHeader (already wrapped), plugin-detail x3 (no definition in hand), PackagedActionsSection (bare fetch without the session language).", "tests": "Pins (objectstack#30390 describes): servedObjectLabel-30390 (6), RecordFormPage.listLinkPlural-11733 (+2), RecordDetailView.relatedListTitlePlural-11733 (+1), RecordPreviewCard (+2), closedAffordanceNotice.i18n-11000 (+2). Reverse leg at 54a922c2 (pre-change source restored tree-only, restored from HEAD, git diff HEAD empty): 9 renamed cases RED, controls GREEN. zh-CN fixture pass: 31 files, 5 English-in-zh-CN fixtures corrected (assertions unchanged) then 5/5 files 31/31 tests. Consumer sweep at 54a922c2, 615 files: 595 passed, 1 skipped, 19 RecordDetailView.* failed to load (new import of useNavTargetLabel pulled MetadataProvider; a test mock read an uninitialized spy) -> helpers moved to a provider-free module at 67d3e713, 28 files re-run: Test Files 28 passed (28), Tests 237 passed (237). Type-check after merging origin/main (2e899586): turbo type-check over app-shell, fields, plugin-form, plugin-gantt, plugin-grid, components, console: Tasks 80 successful, 80 total, VERDICT command-exit 0.", "gates": "head 2e899586; dispatch-gates --ran: 36 derived, 36 run, 0 NOT-MEASURED, 0 UNRUN; every derived family exit 0 (list in gates_ran). Plus ui check:new-line-citations: 0 new citations, exit 0. CI check-runs: in_progress at report time (PR opened as draft just before).", "gates_ran": [ "node scripts/check-adr-0087-registration.mjs --base origin/main :: exit 0", "node scripts/check-adr-0087-registration.mjs --self-test :: exit 0", "node scripts/check-changeset-no-major.mjs --base origin/main :: exit 0", "node scripts/check-closing-keyword-parity.mjs :: exit 0", "node scripts/check-closing-keyword-parity.mjs --self-test :: exit 0", "node scripts/check-comment-mask-corpus.mjs :: exit 0", "node scripts/check-empty-changeset.mjs --base origin/main :: exit 0", "node scripts/check-empty-changeset.mjs --self-test :: exit 0", "node scripts/check-sdui-manifest.mjs :: exit 0", "node scripts/check-sdui-manifest.mjs --self-test :: exit 0", "node scripts/pm/release-rehearsal-clone.mjs --self-test :: exit 0", "node scripts/release-pending-publish.mjs --self-test :: exit 0", "pnpm --dir ui exec vitest run scripts/ :: exit 0", "pnpm --filter @objectstack/spec run check:duration-unit-keys :: exit 0", "pnpm check:changeset-gate-self-tests :: exit 0", "pnpm check:closed-ceremony-text :: exit 0", "pnpm check:cross-package-test-inputs :: exit 0", "pnpm check:dispatcher-error-vocabulary :: exit 0", "pnpm check:driver-memory-census :: exit 0", "pnpm check:engine-double-contract :: exit 0", "pnpm check:error-status-conformance :: exit 0", "pnpm check:gitlink-declared :: exit 0", "pnpm check:nul-bytes :: exit 0", "pnpm check:published-files :: exit 0", "pnpm check:query-options-erasure :: exit 0", "pnpm check:refd-timer-probe :: exit 0", "pnpm check:registry-log-declared :: exit 0", "pnpm check:rest-log-spy-declared :: exit 0", "pnpm check:skill-identifier-liveness :: exit 0", "pnpm check:test-source-alias :: exit 0", "pnpm check:tier-file-adoption :: exit 0", "pnpm check:type-check-coverage :: exit 0", "pnpm check:type-check-debt :: exit 0", "pnpm check:undeclared-dep-imports :: exit 0", "pnpm check:watch-hint-literal :: exit 0", "pnpm check:where-matcher :: exit 0", "pnpm --dir ui check:new-line-citations :: exit 0" ], "dogfood_battery": "n/a — no ! in the PR title and no (narrowing) arm", "line_budget": "31 files, +486/-177 (src +225/-132, tests +261/-45); measure estimated src +110/-45, tests +250: src is higher because the comments on the changed sites were rewritten and the helpers moved to their own module", "files_changed": [ ".changeset/30390-served-object-label-record-surfaces.md", "ui/apps/console/src/components/FormPage.tsx", "ui/packages/app-shell/src/console/AppContent.tsx", "ui/packages/app-shell/src/console/__tests__/AppContent.createLandingOriginPlural-11733.test.tsx", "ui/packages/app-shell/src/console/__tests__/AppContent.recordSaveToastNamesRecord-26172.test.tsx", "ui/packages/app-shell/src/console/home/__tests__/HomeActivity.objectLabel-12238.test.tsx", "ui/packages/app-shell/src/hooks/__tests__/servedObjectLabel-30390.test.ts", "ui/packages/app-shell/src/hooks/servedObjectLabel.ts", "ui/packages/app-shell/src/hooks/useNavTargetLabel.ts", "ui/packages/app-shell/src/layout/ActivityObjectLabel.tsx", "ui/packages/app-shell/src/layout/ConsoleLayout.tsx", "ui/packages/app-shell/src/layout/__tests__/InboxPopover.activityObjectLabel-12212.test.tsx", "ui/packages/app-shell/src/views/ObjectDataPage.tsx", "ui/packages/app-shell/src/views/ObjectView.tsx", "ui/packages/app-shell/src/views/RecordDetailView.recordReadFailure-11902.test.tsx", "ui/packages/app-shell/src/views/RecordDetailView.relatedListTitlePlural-11733.test.tsx", "ui/packages/app-shell/src/views/RecordDetailView.tsx", "ui/packages/app-shell/src/views/RecordFormPage.listLinkPlural-11733.test.tsx", "ui/packages/app-shell/src/views/RecordFormPage.tsx", "ui/packages/app-shell/src/views/appReportIndex.ts", "ui/packages/app-shell/src/views/record-preview/RecordPreviewCard.test.tsx", "ui/packages/app-shell/src/views/record-preview/RecordPreviewCard.tsx", "ui/packages/app-shell/src/views/recordDrawerStack.tsx", "ui/packages/app-shell/src/views/widget-ref-cells/WidgetRefCellFaces.tsx", "ui/packages/components/src/renderers/layout/containers.tsx", "ui/packages/fields/src/RecordHoverCard.tsx", "ui/packages/plugin-form/src/ObjectFormContainer.tsx", "ui/packages/plugin-form/src/closedAffordanceNotice.i18n-11000.test.tsx", "ui/packages/plugin-form/src/closedAffordanceNotice.tsx", "ui/packages/plugin-gantt/src/ObjectGantt.tsx", "ui/packages/plugin-grid/src/RecordPointerCell.tsx" ], "deviations": [ "Body order follows _common.md (维护者速读 before Fixes).", "Harness after-PR assign/review and PR subscription skipped per the dispatch Writes line and os-dev.md.", "Commit trailers are the model-free pair the repo requires, not the harness's model-named Co-Authored-By.", "PackagedActionsSection left unchanged although measured as served: its /meta/object read is a bare fetch without the session Accept-Language." ], "mcp_calls": "0", "api_writes": "3 — git push (branch, not REST); relay pr_create POST /repos/objectstack-ai/objectstack/pulls via repository_dispatch (run 42031760319); this report comment POST /repos/objectstack-ai/objectstack/issues/30390/comments via post-stamped", "open_questions": [], "security_findings": "none", "out_of_scope_findings": [ "carrier: seat domain:ui#3 (ruled out of scope on the Claim) · noted, not filed · plugin-detail record-reference-rail (two objectPluralLabel calls) and record-related-list name a related object by humanize(objectName) through the catalog only; no served definition is in hand, so a renamed object keeps the base translation there · dedupe: related list humanize object label, reference rail plural label served", "carrier: seat domain:ui#3 · noted, not filed · PackagedActionsSection fetchObjectMetadata is a bare fetch without the session Accept-Language, so the packaged-actions table's object column keeps the catalog-first order; drawing its served label would show the browser's language · dedupe: packaged actions object label locale, meta object bare fetch accept-language" ] }objectstack-fleet commentedon Nov 5, 2026
domain:ui#3 · os-bill · session_01Utp6CbPN5UYMnBaNJPJWfG
Landed · PR #30475 · 2026-11-05T15:18Z
8b0fbb87b;Fixes #30390, card closed by the merge. Seat ACCEPT 6658990508 on2e899586, head-move re-check 6659932077 on the landed head3567f3b9(merge of main, PR diff unchanged)..customrename now holds on these surfaces.State change:
pm:dispatchedremoved, assignee cleared.