Repository navigation
meta read: a view stored with no label is served with label = its qualified name (recheck_gate.default), invented by the read-side translator, so the console view tab shows the machine name #23967
Description
Filing gate ①: a user-visible defect with a named landing and a live reproduction. A machine name is shown where the platform's own code says no label was authored.
QA-source: #23942 · studio-authoring · observation (cloud slice comment on #23878; re-checked and filed under #23878)
What happens
The spec declares label optional on a view (packages/spec/src/ui/view.zod.ts:5154, I18nLabelSchema.optional()), with no default. When a view is stored without one, the REST read path still serves a label: its translation step writes back view.label ?? view.name, so the document carries label: "OBJ.default". The console's object page renders that string as the view tab, as served (objectui ObjectView.tsx viewTabLabel), so the user sees recheck_gate.default. A machine name is shown even though the object has a label ("QA Gate" / "QA Gates").
The REST layer already knows this fallback is not a label. For view-container slots it drops it explicitly (meta-item-read-gate.ts:3005-3008: "A label that equals input.name where input had none is the translator's fallback, not a translation, and is dropped"). The single-item read and the list read keep it. A consumer therefore cannot tell an authored label from an invented one without comparing it to name, which is the tolerant-consumer shape PD #12 forbids.
Reach — measured, 2/2 fresh loads
Environment: objectstack 7277c07f (main, 2026-10-16), examples/app-showcase booted from a main worktree, OS_PORT=47321 objectstack dev --ui --seed-admin -p 47321 -d file:…/data.db. Console: objectui daeb77fc (the .objectui-sha pin), built against @objectstack/spec from a35f7a67^ (34b740f2), because the pin does not build on main (#23885 / #23908). check:console-sha matches. Playwright with /opt/pw-browsers/chromium, form sign-in as the seeded admin.
POST /api/v1/packages{"manifest":{"id":"com.qa.recheck","name":"QA Recheck","version":"1.0.0","type":"app","namespace":"recheck"},"enableOnInstall":true}→ 201.PUT /api/v1/meta/object/recheck_gate?package=com.qa.recheck: label "QA Gate", pluralLabel "QA Gates", fieldsnameandkind→ 200.PUT /api/v1/meta/view/recheck_gate.default?package=com.qa.recheck{"name":"recheck_gate.default","object":"recheck_gate","viewKind":"list","isDefault":true,"config":{"type":"grid","columns":["name","kind"]}}, with no label → 200.GET /api/v1/meta/view/recheck_gate.default/layers:overlayandeffectivecarry nolabel.GET /api/v1/meta/view/recheck_gate.default:item.label: "recheck_gate.default". It is appended as the last key, after_diagnostics.- Browser:
/_console/apps/com.example.showcase/recheck_gateshows the header "QA Gates", and the only view tab readsrecheck_gate.default. Same on two fresh loads.
The same fill reaches stock form views. GET /api/v1/meta/view lists showcase_task.form, showcase_task.tabbed, showcase_contact.create and others with label equal to their name.
- Expected: a view with no authored label is served with no
label(ornull), as the container slots already are. The console then falls back to a human string (the object's plural label, or its "All records" wording). - Actual: the served document asserts a label nobody wrote, and it is the machine name.
Where
- objectstack main
7277c07f:packages/spec/src/system/i18n-resolver.ts:481isconst fallback = view.label ?? view.name;inresolveViewLabel.:1186:translateViewwrites it back unconditionally (return { ...view, label, … }).packages/rest/src/meta-item-read-gate.ts:2881: the single-item read runs it throughtranslateMetadataDocument.:2823does the same for the list read.:3023(if (key === 'label' && input.label == null && value === input.name) continue;) drops it for container slots only.- The resolver's own pin,
packages/spec/src/system/i18n-resolver.test.ts:294-303, pins the resolver's return value, not the served document.
- objectui main
023087f63is the consumer half:packages/app-shell/src/views/ObjectView.tsx:956,const text = view.label || view.name || view.id;. Even with the server fixed, a label-less view would still fall back to the machine name here, so the console needs a human fallback too. That is a follow-up on objectstack-ai/objectui, filed when this contract lands.
Done when
- The single-item and list meta reads serve a view with no authored label without an invented
label, the same way the container path does. A REST pin asserts thatGET /meta/view/NAMEfor a label-less stored view carries nolabelequal toname. Translated labels still resolve. - A consumer card on objectstack-ai/objectui is opened for
viewTabLabel's fallback (human string, never the qualified name).
Reader who acts: the REST/i18n read-path owner (domain:services or domain:spec execution seat; triage picks). The diff is in packages/spec/src/system/i18n-resolver.ts translateView / resolveViewLabel or in the REST read gate's view translation.
Dedupe
- MCP
search_issueson objectstack-ai/objectstack, all states: "served view label falls back to view name translateView resolveViewLabel tab shows object.default" → 11 hits, all read. View labels never resolve a translation —resolveViewLabelreads two fields the served view document does not have #4854 (view labels never resolve a translation, closed), finding(spec,i18n):translateObjectnever reads an object's embeddedlistViews, so their labels are served in the authored language whileos i18n extractwrites_viewskeys for them #21006 and [finding] meta(view): GET /api/v1/meta/view/:object answers 500 for a defineView container on an artifact boot — viewTranslationKey reads the absent view.name #22614 (closed) are neighbours. None covers the invented label. - Studio shows machine names where labels exist: Explain access principal chips and result banner, and the list-view Columns chips objectui#12693 (machine names in Studio: Explain chips, Columns chips) does not carry the view tab, so this is not folded there.
Re-checked by a cloud QA session dispatched under #23878 (maintainer ruling there, 「派云卡片复核这 7 条,授权里全部立卡。有时间间隔就行」).
Generated by Claude Code
Activity
objectstack-fleet commentedon Oct 16, 2026
Triage: first grade,
bug·priority:p1·target:v18·domain:cli·area:api·pm:queue· triage seat ·session_01AavokzJ5DndAwitDXvKy4U· 2026-10-16T16:00ZTriage seat (objectstack-wide, seat post #6015). ⛔ Not a claim, ⛔ not a dispatch.
target:v18: a/metaread serves alabelnobody authored. Dropping the invented value narrows the/metadoor's served shape, which is the protocol-first class. Meanwhile the console showsrecheck_gate.defaultas a view tab.domain:cli: the read path ispackages/rest(meta-item-read-gate.ts, whose view-container slots already drop the same fallback). The single-item and list reads take the same rule.viewTabLabelmust then fall back on its own whenlabelis absent. If it does not, file the objectui half as its own card (the self-split rule).objectstack-fleet commentedon Oct 16, 2026
Claim: PM loop round 1 (#23967: the
/metasingle-item and list reads serve a view with no authoredlabelwithout thelabelthe read-side translator invents from its name, by the rule the view-container path already applies, on both hosts through the one read gate) · 2026-10-16T17:08ZSession:
session_018t6a5rvqPRvEDMCVVW9kYTAccount:
os-tesla(the seat's linked user asGET /useranswers it; the card's assignee from this act)Branch:
claude/issue-23967-view-label-not-inventedWorktree:
objectstack-issue-23967Domain:
domain:cliSeat:
domain:cli#2(seat post #22648)Scope:
batch3. Dev runs in flight before this act: #23914 and #23909. #23181 slice 4's dev run has ended; its PR #23994 is in review. This card takes the third slot. Verify-lock depth at this act: 1 (#23914's run holds it; the queue is empty).Order, read at this act: no open
p0orpm:blockingdomain:clicard is inpm:queue.execution-duties.mdrankstarget:board items abovep1. Of the twotarget:v18bugs in the queue, #23909 went to this seat at 16:55Z. This card is the other. #23977 (p1, notarget:) ranks after it.File surface (read on
origin/main2e1562091c; stop on a breach and explain it in the report):packages/rest/src/meta-item-read-gate.ts:translateMetaDocument's single-view arm (about:2876–:2885) andtranslateMetaList's per-element map (about:2823), for the typeviewonly.labelthe translator returns for a view that had none, equal to that view'sname, is not served. This is the ruleprojectViewTranslationalready applies to container slots (about:3005–:3023, [finding] meta(view): GET /api/v1/meta/view/:object answers 500 for a defineView container on an artifact boot — viewTranslationKey reads the absent view.name #22614).RestServer.translateMetaItemand its list twin delegate here. The runtime dispatcher's/metadomain callstranslateMetaListandtranslateMetaEnvelope, both exported from@objectstack/rest; the latter wrapstranslateMetaDocument. The domain file itself is not edited.packages/restbeside the read-gate tests, covering the single-item and list reads:label;.changeset/23967-*.md(@objectstack/rest; see the Clause-② basis).packages/spec(i18n-resolver.ts'resolveViewLabel/translateView, where the fallback is made:domain:specground, and a change there changes an exported function's return type);packages/rest/src/rest-server.ts(PR refactor(rest): move registerUiEndpoints into ui-routes.ts (#23050 slice 10) #23990, [maintainer] refactor(rest): splitpackages/rest/src/rest-server.ts(13,701 lines, 70 commits in 30 days) along itsregister*Endpointsseams, one move-only slice per PR,/metaafter #22877 stage 2 #23050);packages/runtime/src/domains/meta.ts(Malformed JSON request body is silently parsed as {}: a truncated POST /data/:object/query answers 200 with the whole table, and a truncated PATCH answers 200 with an empty update #23914, in flight);ObjectView.tsxviewTabLabel(view.label || view.name || view.id) still shows the machine name until it gets its own human fallback. The card's Done-when files that half on objectstack-ai/objectui when this contract lands, so this seat files it at landing.Container & model:
S-to-M(one rule on three call sites of one module, pins on two reads and two hosts),mode:subagent,model: TIER_DEFAULT(dispatch-gates --tieron this surface: no path-derived mandate). The(narrowing)face owes oneCONTRACT_REVIEW_TIERreview before the queue.Clause-②: no (narrowing)
Basis for the Clause-② line:
/metadoor serves. A view stored without alabelwas servedlabel: "<object>.<key>"on the single-item and list reads, and is served without one. This is the protocol-first class the triage grade names (6219439245).view.zod.tsdeclareslabeloptional with no default, and the read layer already drops the same value for container slots. So the shipped answer was the defect, and no published text promises the invented label.labelas served, and the console tab until its objectui half lands), and follows the repo's breaking-changeset convention, which its gates derive.Responsibility:
the REST read gate's view translation in packages/rest, which both hosts serve /meta reads through (this lane) | the spec resolver resolveViewLabel, which makes the fallback (domain:spec), and objectui's viewTabLabel, which shows it (the objectui half) | a console user who sees recheck_gate.default as a view tab, and every client that reads a served view's labelThread-read: 6219439245
Serial constraints cleared: open PRs read in this act.
meta-item-read-gate.ts,i18n-resolver.tsorview.zod.ts.runtime/src/domains/meta.ts' body catch-all and the transports' body parse; runtime(dispatcher): anonymous GET / PUT / PATCH / DELETE on /api/v1/keys answer 405 METHOD_NOT_ALLOWED instead of the 401 UNAUTHENTICATED the v18 anonymous floor states for every /keys verb — only POST is mounted #23909 holds the dispatcher's/keysmount; [maintainer] refactor(rest): splitpackages/rest/src/rest-server.ts(13,701 lines, 70 commits in 30 days) along itsregister*Endpointsseams, one move-only slice per PR,/metaafter #22877 stage 2 #23050 holdsrest-server.ts. None names this module.Generated by Claude Code
objectstack-fleet commentedon Oct 16, 2026
os-dev-report
{
"issue": 23967,
"status": "done",
"branch": "claude/issue-23967-view-label-not-invented",
"pr": "#24013",
"session": "session_018t6a5rvqPRvEDMCVVW9kYT — subagent run; the parent's harness-stamped id, carried on every commit's Claude-Session line and confirmed by the relay route (CLAUDE_CODE_REMOTE_SESSION_ID)",
"premise_still_valid": true,
"summary": "Reproduced on BASE adce192 on both hosts.
GET /api/v1/meta/view/recheck_gate.defaultandGET /api/v1/meta/viewserved a view stored with nolabelaslabel: \"recheck_gate.default\", on the standaloneos devand on the dispatchercreateHonoAppbuilds. The rule the container path already applied is now ONE module-private helper in packages/rest/src/meta-item-read-gate.ts,withoutInventedViewLabel(input, translated), and all three view sites call it: translateMetaDocument's single-view arm (item read, wrapped by translateMetaEnvelope), translateMetaList's per-element map (list read), and projectViewTranslation (container; its inline check is replaced with the same semantics). A label equal to the view's name where the stored view carried none is no longer served; authored labels (including one equal to the name) and catalog translations are. HEAD serves nolabelkey for the label-less view on both hosts and both reads, in every locale. The changeset is BREAKING,minor,Clause-②: no (narrowing),adr-0087: not-required (no-migration-prescription). The objectui half (viewTabLabel) is left to the seat, as the card's Done-when says.","tests": "New pin file packages/rest/src/meta-view-label-not-invented.test.ts, 39 rows: §1 standalone routes over a real SchemaRegistry and ObjectStackProtocolImplementation, one row per locale x view; §2 translateMetaEnvelope / translateMetaList, the dispatcher's functions; §3 container CONTROL.
pnpm --filter @objectstack/rest exec vitest run --maxWorkers=2 --project local src/meta-view-label-not-invented.test.tspassed 39/39. REVERSE VERIFICATION, the whole file at BASE (on-disk blob 93e978309 == BASE blob): 15 red, exactly the label-less rows on both reads; all authored/translated rows and both §3 container rows green, so the container answer is unchanged. ABLATIONS via scripts/ablation-replace.mjs (anchor 1-to-0, blob changed; restore proven blob == HEAD blob 8fd8cdef6 andgit diff HEADempty): item sitereturn translatedgave 9 red, item-side label-less rows only; list sitereturn outgave 9 red, list-side only; container site (helper bypassed in projectViewTranslation) gave the 2 §3 rows red. No rebuild between legs: the subject resolves to src by relative import (./meta-item-read-gate.js, and ./rest-server.js imports it relatively), so ablation-dist-preflight does not apply. Suites, post-merge at 6ff4da0 (the later commit 203a819 adds only a ledger JSON row), all under os-verify-lock with VERDICT command-exit 0:pnpm --filter @objectstack/rest typecheckexit 0;pnpm --filter @objectstack/rest testexit 0, 288 files, 5941 passed, 326 skipped;pnpm --filter @objectstack/rest test:repoexit 0, 5 files, 250 passed, 11 skipped;pnpm --filter @objectstack/runtime exec vitest run --maxWorkers=2 --project localon the 25 local src/domains/meta-*.test.ts files exit 0, 513 passed;--project repo src/domains/meta-list-projection-parity.test.tsexit 0, 739 passed (runtime aliases @objectstack/rest to src). The same suites were also green pre-merge at 6c1755e.tsc -p packages/rest/tsconfig.test.json --noEmit --listFileslists the new test with 0error TS. LIVE BOOT from a scratch dir outside the repo (examples/app-todo compiled withos compile -o SCRATCH/objectstack.json,os dev --artifact ./objectstack.json --fresh, placeholder admin; recipe: POST /packages 201, PUT object 200, PUT view with no label 200, PUT view labelled 'All gates' 200), with no Accept-Language, en and zh-CN: BASE item 200 label 'recheck_gate.default', list element 200 label 'recheck_gate.default'; HEAD item 200 no label key, list element 200 no label key; authored 'All gates' on both; /layers overlay and effective carry no label on both. DISPATCHER PROBE (new HttpDispatcher(kernel)from the built runtime dist importing the built rest dist): BASE serves label = own name on item and list whenever a locale resolves (default locale or zh-CN); HEAD serves no label key; zh-CN catalog strings ('已标记', '全部闸门') served on both; with no default locale or no i18n service, label is absent on BASE and HEAD alike.","gates": "LOCAL, at final HEAD 203a819:
node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstackderived 72 commands from merge base d132140, after a fresh fetch (the upstream commits since touch no derived input and no packages/rest file). All 72 were run with each exit captured before any pipe, and all 72 exited 0. Among them: check:adr-0087-registration (not-required (no-migration-prescription) accepted), check:changeset-no-major, check:empty-changeset, check:engine-double-contract (1017 pinned), check:test-source-alias, check:cross-package-test-inputs, check:nul-bytes, check:dual-build-cjs-loads (110 entry points across 68 packages load).node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --ran FILEover theCOMMAND :: exit CODErecord printed 'Run reconciliation — 72 derived, 72 run, 0 NOT-MEASURED, 0 UNRUN' and '✓ … a DERIVED zero — all 72 recorded an exit code and none of them is 3'. An earlier union at 6ff4da0 had check:engine-double-contract exit 1 (RETAINED: the new pin's findOne double was unledgered), fixed by the gate's own--write(1 row added, 0 lost) in 203a819, and check:dual-build-cjs-loads exit 3 (PREREQUISITE NOT MET), which measured on the final run. Lint: dispatch-gates names no lint family;pnpm exec eslint --no-inline-config packages/rest/src/meta-item-read-gate.ts packages/rest/src/meta-view-label-not-invented.test.tsexit 0. Local-only families check:dev-prereqs and check:skill-frame-freshness were not owed: no packages/spec build or frame file is touched. CI check-runs on 203a819, read once at about 18:41Z: success for Check PR Size, 'No other open PR may claim the same issue', 'No other open PR may claim the same single-writer path', 'Part-of PR must not also close its card' and 'The card this PR closes must claim this branch'; Packed-tarball smoke skipped; Auto Label queued; in_progress for Check Changeset, Lint · ESLint, Lint · CI, release & engine gates, Lint · PM dispatch-gates, Lint · docs & code guards, Lint · repo & tooling gates, the three Lint · scoped lanes, Type Check · workspace / source gates / consumer gates / debt ledger, Governed Surface Queue Guard, Check Documentation Links, 'Flag docs affected by code changes' and filter. Test Core and Build Core had not appeared yet. CI convergence is the PM's.","mcp_calls": "0 — no MCP GitHub tool was called",
"api_writes": "2 relay strokes as objectstack-fleet[bot], each one session-token POST /repos/objectstack-ai/objectstack/dispatches executed by fleet-write.yml. (1) pr_create (run 38949076029): POST /repos/objectstack-ai/objectstack/pulls (draft forced) + POST /repos//issues/24013/assignees (os-tesla); the relay read back 10474 bytes stored identical, and a REST read confirmed draft:true, the body diff-identical and the session-URL footer once. (2) comment: POST /repos//issues/23967/comments (this report). label-write: none, as dispatched. git push x7 to the branch (not REST). Reads: single-card REST GETs of the issue, its comments, PR 24013 and its check-runs.",
"deviations": [
"File surface +1: scripts/engine-double-contract.pinned.json gains one row (packages/rest/src/meta-view-label-not-invented.test.ts, findOne, pinned 1). check:engine-double-contract REDs a new pinned engine double that the ledger does not record and prescribes
--write; the regeneration printed 0 rows lost and moved no other row. Declared in the PR's 'Surface note'.","Merged origin/main once before opening the PR (AGENTS.md §10), merge commit 6ff4da0, because #23990 had landed in packages/rest (rest-server.ts and ui-routes.ts; no overlap with this diff). Rebuilt the rest closure plus plugin-security and re-ran the suites post-merge.",
"Live boot used examples/app-todo compiled into a scratch artifact rather than the card's showcase, so that it booted from a directory outside the repo. The card's object PUT now needs
sharingModel(422 security-owd-unset without it).","Commit trailers use AGENTS.md's model-free pair (
Co-authored-by: Claude) instead of the harness reminder's model-named trailer, which AGENTS.md and the pre-push hook refuse. The PR footer uses AGENTS.md's session-URL form instead of the harness's suggested footer.","label-write: zero writes, as dispatched. skip-changeset does not apply: the diff publishes @objectstack/rest, so it carries its changeset."
],
"files_changed": [
"packages/rest/src/meta-item-read-gate.ts",
"packages/rest/src/meta-view-label-not-invented.test.ts",
".changeset/23967-view-label-not-invented.md",
"scripts/engine-double-contract.pinned.json"
],
"open_questions": [],
"out_of_scope_findings": [
"class: none (not a filing class) · reach: none measured · PM assumption 5, other translatable types. The object, app, dashboard, dataset, page and picklist translators serve
labelonly from the catalog or the document (conditional spread or?? doc.label); none falls back to name.actiondoes: resolveActionLabel answers action.name and translateAction always writes label. But ActionSchema declares label required (packages/spec/src/ui/action.zod.ts:959), so no schema-valid stored action reaches the fallback · carrier: none; noted in the PR's Acceptance notes, not filed · dedupe: resolveActionLabel action.name fallback, translateAction label, served action label invented","class: none · reach: no served door after this PR · PM assumption 6, for domain:spec. resolveViewLabel's
view.label ?? view.name(packages/spec/src/system/i18n-resolver.ts:481) is unchanged. translateView's callers in this repo: this module's three sites (all now drop the fallback) and the public-form route in packages/rest/src/rest-server.ts (about :9391), which takes only the translatedconfigand keeps its own label reading. packages/cli/src/utils/i18n-extract.ts names both functions in docblocks only, with no import, so the dispatch's 'feeds … the CLI's i18n-extract.ts' is falsified. objectui main 63d00da calls neither (docblock mentions only) · carrier: domain:spec seat; noted, not filed · dedupe: resolveViewLabel fallback view.name, translateView invented label, exported resolver return type","PM assumption 4, consumers; no conflict and nothing to file. GetMetaItemResponseSchema.item is z.unknown() and GetMetaItemsResponseSchema.items is z.array(z.unknown()). ViewItemSchema's label is optional. No packages/client type requires a served view's label, and no test in packages/** or examples asserts that a served view's label equals its name. The CLI's serve-view-container-read integration test asserts authored labels, and the dogfood view-container-cross-package-default test compares the item and list reads, which now take the same rule. objectui's viewTabLabel falls back to view.name · carrier: none",
"carrier: the domain:cli seat, at landing, per the card's Done-when · the objectui half (ObjectView.tsx viewTabLabel,
view.label || view.name || view.id, about :956 on objectui main 63d00da) needs a human fallback; until then the console tab keeps showing a machine name for a label-less view · noted, not filed by dev","class: none (unestablished) · reach: scratch setup only ·
os dev --artifactfrom a directory with no node_modules loggedruntime module load FAILED … Cannot find package '@objectstack/spec' imported fromthe artifact's runtime bundle, and app-todo's hook task_logic was refused at boot. It does not touch /meta. Whether an artifact is meant to boot without its dependencies installed is not established · carrier: none; noted in the PR, not filed · dedupe: artifact runtime bundle bare import @objectstack/spec, os dev --artifact outside project, runtime module load FAILED","carrier: PM (container hygiene, not a repo finding) · /tmp/claude-0/-home-user/ab77ba73-22e7-5d29-a840-c87e921818a0/scratchpad/issue-23805 held 21G (files last written 06:45–08:49Z) and filled the shared disk to 99% at about 18:13Z. One tool output was lost to ENOSPC. By about 18:30Z the space had been freed by someone else (22G available); this run deleted nothing outside its own files"
]
}
Generated by Claude Code
objectstack-fleet commentedon Oct 16, 2026
ACCEPTed: PR #24013 at
203a8192f6·domain:cliseat 2 ·os-tesla· sessionsession_018t6a5rvqPRvEDMCVVW9kYT· 2026-10-16T19:06Z · holder of claim6220711918.6222734061on PR fix(rest)!: the /meta item and list reads serve a view stored with no label without an invented label #24013. Review:## Contract review6222526815,CONTRACT_REVIEW_TIER(the(narrowing)face), PASS on this head. Every check on the head is green or a roster skip, and landing is armed in this act.Fixes), and this seat files the objectui half (viewTabLabel's fallback for a label-less view) on objectstack-ai/objectui, as the Done-when says.Generated by Claude Code
objectstack-fleet commentedon Oct 16, 2026
Landed: PR #24013 →
aefab7c2c6(#23967,Fixes) ·domain:cliseat 2 ·os-tesla· sessionsession_018t6a5rvqPRvEDMCVVW9kYT· 2026-10-16T19:33Zmerged: true, merge commitaefab7c2c6, merged 2026-10-16T19:33Z through the merge queue (enqueued 2026-10-16T19:11Z)origin/mainaefab7c2c6is an ancestor oforigin/main: 4 files, +417 / −11, as reviewed at203a8192f6.meta-item-read-gate.tsdeclareswithoutInventedViewLabel(1 hit)gh-readonly-queue/main/*pr-24013*head remains## Contract review6222526815(CONTRACT_REVIEW_TIER, the(narrowing)face, PASS), ACCEPT6222734061, card pointer6222758377./metasingle-item and list reads serve a view stored with nolabelwithout the label the translator made from its name, on both hosts. Authored labels and catalog translations are served as before.viewTabLabel(ObjectView.tsxabout:956,view.label || view.name || view.id) still shows the machine name for a label-less view. This seat files it on objectstack-ai/objectui in its next filing window and links it here.pm:dispatchedis removed in the stroke after this comment.Generated by Claude Code
objectstack-fleet commentedon Oct 16, 2026
The objectui half is filed: objectstack-ai/objectui#12774 ·
domain:cliseat 2 ·os-tesla· sessionsession_018t6a5rvqPRvEDMCVVW9kYT· 2026-10-16T19:42ZviewTabLabel(packages/app-shell/src/views/ObjectView.tsx:1013on objectui360e27a) falls back toview.name, so a label-less view's tab still shows its qualified name. PR #24013 removed the invented label from the server, which leaves the console exactly as it was until that card lands. This closes the second line of this card's Done-when.Generated by Claude Code