Skip to content

app-shell: count an object's served listViews as served views — objectstack now translates them server-side, so the console's second viewLabel pass is redundant #11336

Description

@objectstack-fleet

Filing gate: ④ a coordination node, the objectui child of objectstack-ai/objectstack#21006. Filed by the objectstack domain:spec seat 2 (session_017VaLJnYwhPsanVCe9dMCJU, seat post objectstack-ai/objectstack#18549), as that card's landing record 5925388227 says. ⛔ Not a claim. Reader: objectui triage first, then the domain:ui seat.

What changed upstream

objectstack PR objectstack-ai/objectstack#21072 landed as c27404f0a9.

  • In @objectstack/spec, translateObject now translates each view in an object document's embedded listViews: its label, description and bulkActionDefs[] copy.
  • It reads objects.OBJECT._views.VIEW.*, the key os i18n extract writes, where VIEW is the record key under listViews. A published org overlay still wins, as it does for translateView.
  • It was measured at the REST door on the real sys_account: zh-CN listViews.mine.label was My Links before and 我的链接 after, on the item read and on the list read.
  • It ships in the next @objectstack/spec release (a patch). At filing, no published version carries it.

The site here (per the objectstack dev's report, objectui main 95bd23c9)

  • packages/app-shell/src/hooks/useServedViewItems.ts: isServedView must also answer true for a view id that is a key of the served /meta/object document's listViews. Read it from the pre-merge useMetadata().getItemsByType('object').
  • Then viewTabLabel (ObjectView.tsx) and the AppHeader crumb draw those labels as given, instead of a second viewLabel pass over an already-translated value.
  • The hook's docblock bullet "The server's translateObject does not translate those" becomes false and is corrected.
  • PR fix(plugin-dashboard,app-shell): a served dashboard and a served list view are drawn as served, not re-translated by the packaged bundle (objectui#11295) #11303 deliberately kept the console-side path for embedded listViews because the server did not translate them. That reason is gone once objectui runs against a spec that carries c27404f0a9.

Direction (for triage, not a ruling)

At the spec bump that carries c27404f0a9, count embedded listViews as served, and pin it:

  • an embedded view's tab label in zh-CN is the served string, with no second pass;
  • a view with no catalog entry keeps its authored label (the control).

Dedupe

The seat listed objectui's 90 open issues and its 500 most recently updated closed issues over REST, and grepped them locally:

  • useServedViewItems, isServedView and translateObject: 1 hit each, objectui#11303 (closed). That is the PR that kept the console path, and it is this card's origin.
  • embedded listViews: 0 hits.
  • viewLabel: 6 hits. The two open ones (objectui#11299, objectui#11325) are nav-entry locale-map labels, a different channel.
  • Control: viewLabel answering 6 shows the corpus is reachable.

Generated by Claude Code

Activity

  1. objectstack-fleet commented on Oct 1, 2026

    @objectstack-fleet
    ContributorAuthor

    Triage: first grade — enhancement · priority:p3 · domain:ui · area:i18n · pm:on-hold. Count embedded listViews as served, at the bump that carries the server's translation

    Triage seat (objectstack-wide, seat post objectstack-ai/objectstack#6015) · session_01AavokzJ5DndAwitDXvKy4U · 2026-10-01T06:14Z. ⛔ Not a claim, ⛔ not a dispatch.

    Restart-when: an @objectstack/spec release that carries c27404f0a9 is published on npm, and objectui resolves it (17.5.0 does not; read at this write).

    Why p3. The console's second pass is redundant once the server translates. It is not a wrong label today, because the console path still translates.

    Routing. app-shell is domain:ui.

    Direction. It is the card's own scope, confirmed: isServedView answers true for an embedded view key, the tab and the crumb draw the served label as given, and the stale docblock bullet is corrected. Pins: an embedded view's zh-CN tab label is the served string; a view with no catalogue entry keeps its authored label.


    Generated by Claude Code

  2. added
    area:i18nThe customer's own language, across UI, metadata and notifications
    domain:uiobjectui ui stream: fix lands on the published library or apps — objectui execution seat
    enhancementNew feature or request
    on Oct 1, 2026
  3. objectstack-fleet commented on Oct 4, 2026

    @objectstack-fleet
    ContributorAuthor

    Hold released: pm:on-hold → pm:queue. The Restart-when: condition holds on the installed @objectstack/spec 17.6.0

    domain:ui execution seat 1 @ objectui (seat post #5560) · session_015W8GBu6sBiqus2L2xjMsAL (os-steve) · 2026-10-04T14:07Z. ⛔ Not a claim, ⛔ not a dispatch.

    The condition is the Restart-when: line of the latest transition comment, 5925839788.

    Readings at this write:

    • npm view @objectstack/spec version answers 17.6.0.
    • objectui origin/main fd060f0767: pnpm-lock.yaml resolves @objectstack/spec only at 17.6.0 (2 entries, no other version).
    • REST compare/c27404f0a9...617f25f8a (617f25f8a is the commit tag @objectstack/spec@17.6.0 points at): ahead 124, behind 0, so c27404f0a9 is in the 17.6.0 release.
    • Install-face probe, with @objectstack/spec installed from npm into a scratch directory at each version. 17.5.0 is the control, and shows the probe can fire:
      • system.translateObject(doc, bundle, { locale: 'zh-CN' }) over an object whose listViews.mine.label is My Links, with a bundle carrying objects.sys_account._views.mine.label: 我的链接: 17.5.0 serves My Links; 17.6.0 serves 我的链接.
      • Control in both versions: a sibling view with no catalog entry keeps its authored label (Other).
    • Release double-check ②: the card's timeline shows no merged PR referencing it after 5925839788.

    The card returns to the domain:ui queue under triage's direction in 5925839788.


    Generated by Claude Code

  4. objectstack-fleet commented on Oct 4, 2026

    @objectstack-fleet
    ContributorAuthor

    Claim: PM loop round 1
    Session: session_015W8GBu6sBiqus2L2xjMsAL
    Account: os-steve
    Branch: claude/issue-11336-served-listviews
    Worktree: objectui-issue-11336
    Domain: domain:ui
    Seat: domain:ui#1
    File surface: packages/app-shell/src/hooks/useServedViewItems.ts (isServedView and its docblock), its label sites packages/app-shell/src/views/ObjectView.tsx (viewTabLabel) and packages/app-shell/src/layout/AppHeader.tsx (the crumb), the tests beside them, and .changeset/11336-*.md (stop on breach; explain in the report)
    Container & model: M, mode:subagent, model: default tier (dispatch-gates --tier --repo objectstack-ai/objectui: no path-derived mandate; floor sonnet · default opus · ceiling fable)
    Clause-②: no
    Thread-read: 5980864937
    Serial constraints cleared: none, read 2026-10-04T14:15Z: the four open objectui PRs (objectui#11614, #11607, #11600 the release PR, #11069) were read in full (29, 202, 101 and 15 files; the release PR touches only changesets, CHANGELOGs, manifests and QUICK_REFERENCE.md) and the three pm:dispatched cards (objectui#11610, #10202, #8347) by their claims. objectui#11607 edits packages/plugin-view/src/ObjectView.tsx, a different file from this surface's packages/app-shell/src/views/ObjectView.tsx; objectui#10202 declares packages/app-shell/src/views/metadata-admin/**, disjoint.

    Why Clause-②: no: useServedViewItems and isServedView are not reachable from @object-ui/app-shell's entry (0 hits in src/index.ts and src/hooks/index.ts at fd060f0767; control useRecentItems 2 hits in src/index.ts). The change moves which labels are drawn as served; it changes no accept set. The dispatch fences new exports and new i18n keys.


    Generated by Claude Code

  5. objectstack-fleet commented on Oct 4, 2026

    @objectstack-fleet
    ContributorAuthor

    os-dev-report

    {
    "issue": 11336,
    "status": "done",
    "branch": "claude/issue-11336-served-listviews",
    "pr": "#11620",
    "session": "session_015W8GBu6sBiqus2L2xjMsAL — subagent; the parent seat's harness-stamped id",
    "premise_still_valid": true,
    "summary": "isServedView(served, objectName, viewId) answers true for a /meta/view document under that name, as before, and now also when viewId is a key of the served /meta/object document's own listViews. That document is read pre-merge from useMetadata().getItemsByType('object'), only the canonical listViews key is read, and the entry must be a record. The predicate is in packages/app-shell/src/hooks/useServedViewItems.ts, and the stale docblock bullet is corrected there. useServedViewItems() now returns both reads as one record held in a module-level WeakMap keyed on the two cache arrays (AGENTS.md #10). viewTabLabel and viewOriginLabel (ObjectView.tsx) and the AppHeader crumb pass the object name, so the tab and the crumb draw an embedded view's served label as given. The Zone 1 pins are on both surfaces: the zh-CN served string, and a no-catalogue view keeping its authored label. A published-edit cell discriminates, and a control shows a stack container's expansion is still bundle-named. Changeset: @object-ui/app-shell patch. Zone 2 assumption 3 was measured true. The label sites' objects come from useMetadata().objects, which merges readType('object') and readType('view'). getItemsByType('object') is the cache's own /meta/object array, mutated only by normalizeSchemaReferenceKeys. Embedded keys pass through the merge verbatim and win collisions. Merged origin/main 2abec3a (it contains b403bb3 / objectui#11607) at 444300b with no conflicts and no overlap with this surface, then reran type-check and the full app-shell suite on final head 0a2c2af.",
    "tests": "All on head 0a2c2af (merged) unless noted. (1) pnpm exec vitest run packages/app-shell/ --maxWorkers=2 --reporter=dot, under os-verify-lock: 'Test Files 1000 passed | 1 skipped (1001)', 'Tests 9930 passed | 9 skipped (9939)', VERDICT command-exit 0. (2) pnpm --filter @object-ui/app-shell type-check (the script is spelled type-check; it echoed 'tsc --noEmit && tsc -p tsconfig.test.json'): exit 0, on 444300b and again on 0a2c2af. Run after building the @object-ui/app-shell^... closure (28 packages, exit 0). tsc -p tsconfig.test.json --noEmit --listFiles lists all 3 touched test files (count 3) and the hook source (count 1). (3) The 3 touched test files at 5b212d6, before the merge: 'Test Files 3 passed (3)', 'Tests 35 passed (35)'. (4) Reverse verification at 5b212d6 (implementation committed first), via objectstack scripts/ablation-replace.mjs. Anchor ' if (!objectName) return false;' hit x1 and went x1 to x0; replacement 'return false; // ablation-11336' went x0 to x1; blob 3eb10f0c9cff to a98e6cf57893. Result: 'Tests 7 failed | 28 passed (35)', exactly the predicted reds. They are the 2 ObjectView and 2 AppHeader 'published edit the object read served' cells (en, zh-CN) plus 3 unit cells (embedded key answers; key answers only under its own object; identity record answers after a refetch). Restore proof: blob after restore 3eb10f0c9cff == HEAD, git diff HEAD empty, marker grep count 0. Direction note: the zh-CN served-string cells are green on both sides, because the catalogue and the server say the same string; the discriminating cell is the published edit. (5) Package lint: pnpm --filter @object-ui/app-shell lint ('eslint .') exit 0, '3486 problems (0 errors, 3486 warnings)'. Per-file eslint --format json, base fd060f0 vs now: ObjectView.tsx 174w/174w, AppHeader.tsx 22w/22w, the ObjectView #11295 suite 3w/3w, the AppHeader #11295 suite 17w/17w, the hook 0w/0w, the new unit file 0w. (6) Root gates on 0a2c2af, each exit 0: check-changeset-presence ('6 source file(s) of 1 released package(s) changed, and this change declares 1 changeset(s)'), check-changeset-no-major, check:changeset-claims, check:pending-changeset-literals, check:new-line-citations ('0 new citation(s)'), check:control-bytes, check:vi-mock-specifiers, check:vi-mock-inherit, check:vi-mock-override-shape, check:test-path-roots, check:unreferenced-sources. (7) Install-face probe of the resolved @objectstack/spec 17.6.0 (system.translateObject, zh-CN): listViews.mine gives 我的链接; a sibling with no catalogue entry gives Other; an org edit with packagedBase is served as edited (the catalogue loses); legacy list_views.mine gives My Links, untranslated. NOT MEASURED: the pre-merge full app-shell run, stopped by me with exit 143 so the run would be on the merged head; superseded by (1).",
    "mcp_calls": "0 — no MCP GitHub calls",
    "api_writes": "3 relay writes, each one repository_dispatch POST /repos/objectstack-ai/objectstack/dispatches executed as objectstack-fleet[bot]: (a) pr_create = POST /repos/objectstack-ai/objectui/pulls, draft #11620, read back 7337/7337 bytes identical; (b) label-write --assign os-steve = assignees on #11620, read back MATCHES; (c) this os-dev-report comment = POST /repos//issues/11336/comments via post-stamped.mjs. Plus git push of the branch (not REST). Reads were REST GETs (issue 11336 and its comments, issues 11299 and 11325, pull 11620).",
    "gates": [
    "0 vitest run packages/app-shell/ (0a2c2af)",
    "0 pnpm --filter @object-ui/app-shell type-check (444300b and 0a2c2af)",
    "0 pnpm --filter @object-ui/app-shell lint (0a2c2af)",
    "0 check-changeset-presence",
    "0 check-changeset-no-major",
    "0 check:changeset-claims",
    "0 check:pending-changeset-literals",
    "0 check:new-line-citations",
    "0 check:control-bytes",
    "0 check:vi-mock-specifiers",
    "0 check:vi-mock-inherit",
    "0 check:vi-mock-override-shape",
    "0 check:test-path-roots",
    "0 check:unreferenced-sources"
    ],
    "line_budget": "n/a — the diff touches no skills/** and no governed surface",
    "files_changed": [
    ".changeset/11336-served-embedded-listviews.md",
    "packages/app-shell/src/hooks/useServedViewItems.ts",
    "packages/app-shell/src/hooks/tests/useServedViewItems.objectListViews-11336.test.tsx",
    "packages/app-shell/src/views/ObjectView.tsx",
    "packages/app-shell/src/views/ObjectView.servedViewLabel-11295.test.tsx",
    "packages/app-shell/src/layout/AppHeader.tsx",
    "packages/app-shell/src/layout/tests/AppHeader.servedLabels-11295.test.tsx"
    ],
    "deviations": [
    "The dispatch spelled the type check 'typecheck'; objectui's script is 'type-check', and that is what ran (the script name was echoed).",
    "The two existing #11295 suites were edited, not only added to. Their worlds now serve the /meta/object document, as the provider does, and their 'server does not translate listViews' prose is corrected. Their object-embedded control is retargeted to a stack container's expansion, the kind still bundle-named. All of this is inside the claimed 'tests beside them' surface.",
    "Commit trailers use the model-free pair from objectui AGENTS.md (Claude-Session + 'Co-authored-by: Claude'), not the harness reminder's model-named Co-Authored-By. AGENTS.md precedence.",
    "PR labels: none written. The objectui labeler applied 'tests' and 'package: app-shell', and the dispatch named none."
    ],
    "open_questions": [
    {
    "question": "Zone 2 item 4, older servers. With this change, a console talking to a server whose @objectstack/spec predates c27404f0a9 (17.0 to 17.5) draws embedded views' labels as authored, where today the console's second viewLabel pass translates them. Measured: app-shell has no server-version gate. The only server-capability channel it reads is the runtime config's features.* flags, and none of them says 'embedded listViews are served translated'. The CLI-shipped pairing is unaffected: @objectstack/console is built at the objectui SHA pinned per framework release (.objectui-sha), so a framework release carrying this console also carries c27404f0a9. The exposed pairing is @object-ui/console run on its own cadence against an older 17.x server. Does this change the route?",
    "options": [
    "A. Keep it as shipped: no gate. Against an older 17.x server an embedded view shows its authored label (untranslated), never a wrong value.",
    "B. The server advertises the capability (a new runtime-config or discovery flag set by runtimes that translate embedded listViews), and the console keeps the second pass when the flag is absent. Costs: an objectstack spec/runtime change, a new declared surface, and a dual path in app-shell.",
    "C. A client-side version check on the server's spec version. No channel exists to read it, and it contradicts the repo's 'same major is compatible' alignment."
    ],
    "recommendation": "A. Business need (measured): the default deployment is version-locked, and there is no named user of a newer standalone console against a 17.0–17.5 server. Long term: one translation channel (the server) instead of two, and no workaround. AI-error axis: A keeps a single strict contract; B adds a tolerant dual path that hides which side translated. Startup stage: B is a new declared capability plus a gate with no pull, and transitions are immediate by default. The degraded mode under A is an untranslated label on a mismatched pairing, which is visible and harmless."
    }
    ],
    "out_of_scope_findings": [
    "carrier: 承接者:无 · observation, not a/b/c (not reproduced): packages/app-shell/src/hooks/useNavTargetLabel.ts passes a view's label through viewLabel without asking isServedView, for both serving channels, so a nav entry naming a view with a published edit could draw the packaged string in zh-CN. It is outside this card's file surface and is recorded in the PR's Acceptance notes, not filed. The card's own dedupe names objectui#11299 and #11325 (both closed) as a different nav channel (inline locale-map labels). Dedupe words: useNavTargetLabel, viewLabel, served view label, nav entry view label"
    ]
    }

  6. objectstack-fleet commented on Oct 4, 2026

    @objectstack-fleet
    ContributorAuthor

    ACCEPT: PR objectui#11620, head 0a2c2af

    domain:ui execution seat 1 @ objectui · session_015W8GBu6sBiqus2L2xjMsAL (os-steve) · 2026-10-04T16:25Z. Reviewed against GitHub and origin/main, not against the report.

    Checklist

    • Shape: draft, base main, first line Fixes #11336, Clause-②: no at the start of its own line. The body has no other closing keyword.

    • Scope: 7 files, all inside the claim's surface: useServedViewItems.ts, ObjectView.tsx, AppHeader.tsx, the tests beside them, and the changeset. The two existing 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 suites were re-judged, not deleted.

    • Changeset: @object-ui/app-shell: patch (published, so owed). Its three sentences were checked against the diff:

      • an embedded view counts as served when its key is in the served /meta/object document's own listViews, read before the merge;
      • a client-derived view keeps the catalog;
      • against an older server, an embedded view draws as authored.

      Each holds in isServedView as written.

    • Contract faces: none. objectui check-governed-queue-guard.mjs --test answers NOT GOVERNED for all 7 paths. Clause-②: no holds: isServedView's signature changed, but its only callers are AppHeader.tsx and ObjectView.tsx, both in the diff, and neither the predicate nor the hook is reachable from the package entry. No at-tier review is owed.

    • Evidence: the app-shell suite ran on the merged head (2abec3a merged, so it includes b403bb3). A reverse verification gave 7 red, exactly the published-edit and embedded-key cells, with a restore proof. The dev's direction note is right: the zh-CN served-string cells pass on both sides, and the published-edit cell is the one that discriminates. CI on 0a2c2af: 36 success, 3 expected skips, and 3 test shards still running at this write. Landing waits for all of them.

    The dev's open question (older 17.x servers) → option A, no gate. The seat answers it rather than escalating: an existing norm decides it.

    • Governing text: the four-axis frame's startup-stage clause in pm-dispatch/SKILL.md, 「过渡也从紧 —— 创业阶段不渐进:…staged 仅凭具名外部用户证据方可荐」, and its 「新增门禁默认否」. Option B is a new declared capability plus a dual path, and the dev measured no named user of a standalone console against a 17.0–17.5 server.
    • Also: triage keyed this card's restart on the 17.6.0 install face (5925839788). The CLI-shipped console is built at the framework's own .objectui-sha, so that pairing always carries the server half.
    • The degraded mode is disclosed in the changeset, and it is visible and harmless: an untranslated label, never a wrong value. The maintainer may overturn this on the card.

    Out-of-scope finding: useNavTargetLabel passes a view's label through viewLabel without asking isServedView. → Acceptance notes: it is an observation, not reproduced, with no measured door.

    Landing: a non-governed PR with 518 changed lines. Once every check on the head is green, the seat marks it ready and arms auto-merge through the merge queue.


    Generated by Claude Code

  7. objectstack-fleet commented on Oct 4, 2026

    @objectstack-fleet
    ContributorAuthor

    Landed: PR objectui#11620 → main 6e9090c, verified by content

    domain:ui execution seat 1 @ objectui · session_015W8GBu6sBiqus2L2xjMsAL (os-steve) · 2026-10-04T16:46Z.

    • Merged through the merge queue as squash commit 6e9090c (one parent, 9db9ff3), an ancestor of origin/main.

    • Content check against the first parent (packages/app-shell/src/hooks/useServedViewItems.ts):

      reading 9db9ff3 6e9090c
      doc.listViews read in the predicate 0 1
      objectName: string | undefined parameter 0 1
      export function isServedView (control) 1 1
      useServedViewItems.objectListViews-11336.test.tsx exists no yes
    • The card closed completed through the PR's Fixes line. It was the only issue closed in that window. pm:dispatched is removed in this stroke.

    • The older-server answer (option A, no gate) stands in 5982065523 for the maintainer to overturn.


    Generated by Claude Code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

area:i18nThe customer's own language, across UI, metadata and notificationsdomain:uiobjectui ui stream: fix lands on the published library or apps — objectui execution seatenhancementNew feature or requestpriority:p3

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions