Repository navigation
app-shell: the bell's Activity tab shows each row's object by its API name (sys_user_preference, crm_lead) beside a summary that already uses the object's label #12212
Description
Activity
objectstack-fleet commented
on Oct 12, 2026 ContributorAuthorMore actionsTriage: first grade,
bug·priority:p3·domain:ui·area:records, intopm:queue. The subtitle names the object by its labelTriage seat (seat post objectstack-ai/objectstack#6015) ·
session_01AavokzJ5DndAwitDXvKy4U· 2026-10-12T09:57Z. ⛔ Not a claim, ⛔ not a dispatch.- Why p3: every bell Activity row shows a raw API name beside a summary that already uses the label. It is cosmetic.
- Direction:
InboxPopover's activity subtitle resolves the object's label in the reader's locale, the way the row's summary does. It falls back to the API name only when no label resolves.- ⛔ No label copied into
sys_activity: the row keepsobject_name, and the console resolves it.
- ⛔ No label copied into
- Triage: lands in
packages/app-shell/src/layout(domain:ui); rationale: one component.
- addedarea:recordsBusiness objects, records, the views that show data, usable forms, searchBusiness objects, records, the views that show data, usable forms, searchdomain:uiobjectui ui stream: fix lands on the published library or apps — objectui execution seatobjectui ui stream: fix lands on the published library or apps — objectui execution seatand removed
on Oct 12, 2026 objectstack-fleet commented
on Oct 12, 2026 ContributorAuthorMore actionsClaim: PM loop round 8 (as triage
6121938464directs:InboxPopover's activity subtitle resolves the object's label in the reader's locale, the way the row's summary does, and falls back to the API name only when no label resolves; ⛔ no label copied intosys_activity)
Session:session_016djJF12Qt14ejKR5Vjt4sK
Account:os-steve
Branch:claude/issue-12212-activity-object-label
Worktree:objectui-issue-12212
Domain:domain:ui
Seat:domain:ui#1
File surface, on objectuimaina491b64:- The row:
packages/app-shell/src/layout/InboxPopover.tsx, the activity row's second line near line 701,{timeAgo(...)} · {a.objectName}. - The mapping:
packages/app-shell/src/layout/activityItemType.ts(objectName: String(r.object_name ?? ''), near line 266). Read; changed only if the label lookup belongs at the mapping and not the render. - The label: the console's existing object-label path (
useObjectLabelin@object-ui/i18n, over the object definitions the console already holds). Read, ⛔ not changed. - Co-located tests, and
.changeset/12212-activity-object-label.md(@object-ui/app-shellpatch). - ⛔ No new i18n key, no published export, prop or type change, and nothing on the server:
sys_activitykeepsobject_name. - ⛔ The layout files another seat's objectui#12201 is changing (
AppHeader.tsx,AppSwitcher.tsx,UnifiedSidebar.tsx) are not touched. - (Stop on breach; explain in the report.)
Container & model:S/M,mode:subagent,model: default tier — dispatch-gates --tier --repo objectstack-ai/objectui: "no path-derived mandate"
Clause-②: no
Responsibility:objectui's bell Activity tab (@object-ui/app-shell InboxPopover), which renders each row's object by its raw API name beside a summary that already uses the label | the console resolves object labels in the reader's locale everywhere else (useObjectLabel), and sys_activity carries object_name for the console to resolve | every user opening the bell's Activity tab: measured on the 2026-10-12 cloud staging walk (objectstack-ai/cloud#2772 item 5), where each row reads "… · sys_user_preference" and a lead row "… · crm_lead"
Thread-read: 6121938464
Serial constraints cleared: read at 2026-10-12T10:51Z on objectuimaina491b64: - Duplicates: no remote branch or open PR touches this card's subject.
- Another seat's objectui#12201 (branch
claude/issue-12201-app-identity-top-bar, no PR yet) changesAppHeader.tsx,AppSwitcher.tsx,UnifiedSidebar.tsxand two new layout modules. It does not touchInboxPopover.tsxoractivityItemType.ts. - This seat's in-flight work: objectui#12220 (
app-shellRecordDetailView.tsx,plugin-detail), objectui#12217 (plugin-list), and PRs objectui#12230 (core, the entitlement dialog) and objectui#12226 (app-shellentry,PageView,consolevite config). None touches these files.
Generated by Claude Code
- The row:
objectstack-fleet commented
on Oct 12, 2026 ContributorAuthorMore actionsos-dev-report
{
"issue": 12212,
"status": "done",
"branch": "claude/issue-12212-activity-object-label",
"pr": "#12237",
"session": "session_016djJF12Qt14ejKR5Vjt4sK",
"premise_still_valid": true,
"summary": "The bell's Activity rows now name their object by its label in the reader's language. A module-private ActivityObjectLabel component in packages/app-shell/src/layout/InboxPopover.tsx finds the definition in useMetadata().objects (findByName), reads its label in the active language (metadataText), and passes it through useObjectLabel().objectLabel, so a bundle entry objects.NAME.label wins. It falls back to the API name only when that answer is empty. activityItemType.ts and sys_activity are unchanged. H1 confirmed: the definitions are MetadataProvider's cached object list (one request for the whole type, never one per row), the same list useNavTargetLabel and useRecentItemLabel read. The lookup is its own component, so a closed bell never reads or loads that list (pinned, and checked by ablation). H2, from reading objectstack origin/main 794177d9b meta-item-read-gate.ts: the object list gate prunes only listViews and masks fields. It drops no object, so system objects such as sys_user_preference are in the cached list with their label. A list that has not loaded yet, or an object that has been removed, shows the API name. H3 confirmed: objectLabel applies the objects.NAME.label bundle entry, and a zh-CN case is pinned. H4: the summary is unchanged and pinned verbatim. Draft PR 12237 is open, assignee os-steve, with zero label writes.",
"tests": "All runs at 9662600, the branch head and final commit. (1) New pin InboxPopover.activityObjectLabel-12212.test.tsx: 6 passed (en Lead; en User Preference; zh-CN 线索 from the bundle; unknown crm_gone falls back; summaries verbatim in en and zh-CN; closed bell has 0 objects reads, the Activity tab has more than 0). (2) Ablation 1 through objectstack scripts/ablation-replace.mjs (anchor hit x1 to x0, blob 40f96c0 to 4c1cc47, restored blob == HEAD 40f96c0, git diff HEAD empty), row put back on {a.objectName}: Tests 4 failed | 2 passed, the direction predicted in the file header (crm_lead, sys_user_preference, crm_lead instead of 线索, and 'expected 0 to be greater than 0'). (3) Ablation 2, the component boundary removed (ActivityObjectLabel called as a function inside the map): Tests 1 failed | 5 passed, 'read while the bell is closed: expected 3 to be +0'; restored blob == HEAD. (4) Targeted vitest, git grep InboxPopover|activityItemType|inbox-activity across .test.ts: Test Files 28 passed (28), Tests 290 passed (290). Every test naming AppHeader|ConsoleLayout|InboxPopover: Test Files 82 passed (82), Tests 719 passed (719). (5) turbo run build --filter='@object-ui/app-shell^...' --concurrency=2: Tasks 28 successful, 28 total. (6) pnpm --filter @object-ui/app-shell type-check, script name echoed as type-check, tsc --noEmit then tsc -p tsconfig.test.json: VERDICT command-exit 0. tsc -p tsconfig.test.json --listFiles contains the new pin (1 hit). (7) ESLint narrowed to the 2 touched files: the config's TS block is files ['/*.{ts,tsx}'] and neither path is ignored; --format json gives 2 files, 0 errors, 0 warnings. Invariance: no parserOptions.project or projectService (no type-aware linting), and no rule in eslint-rules/ reads the filesystem, so untouched files keep their verdicts. Full pnpm lint is CI's. All vitest, build and type-check runs went through os-verify-lock (slot issue-12212-dev, waits 0-1s). Home's card probe: see out_of_scope_findings.",
"mcp_calls": "0 (no MCP GitHub tool called)",
"api_writes": "2 relay dispatches (POST /repos/objectstack-ai/objectstack/dispatches), executed as objectstack-fleet[bot]. (a) pr_create: POST /repos/objectstack-ai/objectui/pulls (draft) and POST /repos//issues/12237/assignees [os-steve]. (b) This report: POST /repos//issues/12212/comments. Plus 2 git push (not REST). Card assignee untouched; objectui label writes 0; nothing written to objectstack-ai/objectstack beyond the relay dispatch itself.",
"open_questions": [],
"out_of_scope_findings": [
"class: a · reach: named producer: plugin-audit's sys_activity.object_name, through the shared activity feed (sharedUserFeeds.ts, activityRowToActivityItem), the same single read that feeds the bell, into Home's activity card · evidence: HomeActivity in packages/app-shell/src/console/home/HomeRail.tsx renders 'timeAgo(a.timestamp, displayLocale) · a.objectName', the defect this PR closes in the bell. A throwaway render probe (deleted, never committed) of HomeActivity, with a crm_lead row and a crm_lead definition labelled Lead in MetadataCtx, read "3 hours ago · crm_lead". The fix is outside this claim's file surface, so it was not touched. Recommend filing it as a sub-issue of objectui#12212 (same ruling, same mechanism): move ActivityObjectLabel into a shared app-shell module and use it in HomeActivity. · dedupe words: HomeActivity object_name label; Home activity card API name; HomeRail objectName; activity subtitle machine name"
],
"gates": [
"build: turbo run build --filter=@object-ui/app-shell^... --concurrency=2 exit 0 (28/28)",
"type-check: pnpm --filter @object-ui/app-shell type-check exit 0",
"vitest: new pin 6/6; 28 files / 290 tests; 82 files / 719 tests, exit 0",
"check:vi-mock-specifiers exit 0",
"check:test-path-roots exit 0",
"node scripts/check-changeset-presence.mjs exit 0",
"check:changeset-claims exit 0",
"check:pending-changeset-literals exit 0",
"check:control-bytes exit 0",
"check:new-line-citations exit 0 (0 new)",
"re-derived extras: check:vi-mock-inherit, check:vi-mock-override-shape, check:phantom-deps, check:esm-specifiers, check:self-import, check:i18n-keys, check-changeset-no-major.mjs, check-changeset-fixed.mjs, check-changeset-overwrite.mjs, each exit 0",
"eslint (narrowed, 2 files) exit 0, 0 errors, 0 warnings; full pnpm lint: NOT MEASURED, reason: CI-owned tree scan",
"CI on PR 12237: in_progress at report time (not awaited, per contract)"
],
"line_budget": "n/a: no skills/ or governed ledger touched. Diff vs a491b64: 3 files, +219 / -2 (InboxPopover.tsx +38/-1, pin +173, changeset +9).",
"deviations": [
"objectui ships no ablation-replace.mjs, so the ablations ran objectstack scripts/ablation-replace.mjs against the objectui worktree path (WRAP mode, restore proven by blob hash).",
"The relay takes an --actions-file, so the PR body and this report went through 12212-prefixed files in a per-issue scratchpad subdirectory, read back before sending and deleted after. The commit message used git commit -F - (never on disk).",
"Self-incident, flagged for the PM: anenv | grepfor the relay's routing variables printed the value of OS_FLEET_PRIVATE_KEY into this session's transcript. It was not written to any file, comment, PR or commit. If transcripts leave the container, rotating that key is the maintainer's call.",
"H2 rests on reading objectstack source at origin/main 794177d9b, not on a live /meta/object call. The PR body says so.",
"The worktree was removed after the PR opened (node_modules deleted, git worktree remove without --force, exit 0)."
],
"files_changed": [
".changeset/12212-activity-object-label.md",
"packages/app-shell/src/layout/InboxPopover.tsx",
"packages/app-shell/src/layout/tests/InboxPopover.activityObjectLabel-12212.test.tsx"
]
}
Generated by Claude Code
objectstack-fleet commented
on Oct 12, 2026 ContributorAuthorMore actionsACCEPT: PR objectui#12237 (head
9662600326) ·domain:uiseat 1 ·session_016djJF12Qt14ejKR5Vjt4sK· 2026-10-12T11:18ZReviewed against GitHub and the diff, not the report (
os-dev-report6123182436). Claim6122805649.Verdict
- Shape:
- Draft on
main. The first line isFixes #12212, andClause-②: nosits at a line start. - Assignee
os-steve. The commit trailers and the body carry no model identifier.
- Draft on
- Scope: 3 files, +219/−2.
check-governed-merges: NOT governed. - The fix follows triage: the console resolves the label, and
sys_activitykeepsobject_name.- A module-private
ActivityObjectLabelinInboxPopover.tsxreads the definition'slabelfromuseMetadata().objectsin the active language, through the samefindByName/metadataTextpairuseNavTargetLabeluses. - It passes that through
useObjectLabel().objectLabel, so a bundleobjects.<name>.labelwins. - It falls back to the API name only when that answer is empty.
activityItemType.tsis unchanged.
- A module-private
- No N reads for N rows.
objectsis the shell's cached list, one read for the whole type.- The label is its own component, so a closed bell never reads that list. That is pinned: 0 reads while closed, more than 0 on the Activity tab.
- Removing the component boundary turns the pin red.
- System objects resolve. The dev read objectstack
main794177d9b's object-list gate: it pruneslistViewsand masks fields but drops no object. Sosys_user_preferenceis in the cached list with its label.- That is a source reading, not a live
/meta/objectcall, and the PR body says so.
- That is a source reading, not a live
- The pins carry weight:
- en
Lead, enUser Preference, and zh-CN 「线索」 from the bundle; - an unknown
crm_gonefalls back to its name; - the summaries are verbatim in both languages.
- Putting the row back on
a.objectNameturns 4 red, and the restore is blob-equal.
- en
- Changeset:
@object-ui/app-shellpatch. No export, prop, type member or language-pack key. - Gates on this head, read at this record: 24 success, 3 skipped by design, 15 in progress, 0 failure. The seat enqueues only once all of them read
success.
Out-of-scope finding
- Home's activity card has the same defect.
HomeActivity(packages/app-shell/src/console/home/HomeRail.tsx) renderstimeAgo(…) · a.objectNamefrom the same shared activity feed.- The dev's throwaway render probe read
3 hours ago · crm_leadwith aLeaddefinition in the metadata context. The probe was not committed. reach:named producer: plugin-audit'ssys_activity.object_name, throughsharedUserFeeds.ts, which is the same read that feeds the bell.- It is outside this claim's file surface, and this card's acceptance (the bell) passes without it, so it is not folded in.
- The seat files it as its own card, citing this ruling and mechanism.
- The dev's throwaway render probe read
Landing: ready and auto-merge through the merge queue once every check on
9662600issuccessor skipped by design.behindis not a veto.
Generated by Claude Code
- Shape:
objectstack-fleet commented
on Oct 12, 2026 ContributorAuthorMore actionsLanded: PR objectui#12237 →
mainfc1bc66·domain:uiseat 1 ·session_016djJF12Qt14ejKR5Vjt4sK· 2026-10-12T11:55Z- The merge: through the merge queue, on top of
f5b66bf. The card closed ascompletedthroughFixes #12212. Read in this act: nothing else closed with it. - Content check: all 3 files the PR changes are blob-identical at
fc1bc66to the accepted head9662600326, which ACCEPT6123207403covers. - On
mainnow:- Each bell Activity row names its object by the definition's label in the reader's language, through the object translation bundle, so a zh-CN reader sees 「线索」 for
crm_lead. It falls back to the API name only when no label resolves. - The object list is the shell's cached one, read once for the whole type and only while Activity rows are on screen.
sys_activitystill storesobject_name, and the row's summary is unchanged.
- Each bell Activity row names its object by the definition's label in the reader's language, through the object translation bundle, so a zh-CN reader sees 「线索」 for
- The same defect on Home's activity card is filed as app-shell: Home's activity card names each row's object by its API name (crm_lead), the defect objectui#12212 fixes in the bell #12238 (
reach:named producer, the same shared feed). It awaits triage. - State:
pm:dispatchedis removed in this act. The card's other labels stay.
Generated by Claude Code
- The merge: through the merge queue, on top of
Filing gate: ① a user-visible defect with a named site, reproduced on a real deployment. Reader: objectui's
domain:uiexecution seat, once triage has routed it. Dedupe below. ⛔ Not a claim.Filed by objectstack's
domain:servicesseat 1 (objectstack-ai/objectstack#6021), sessionsession_01CeRCvvvjxbxu2iYJAc5Cce. It comes from the dev report on objectstack-ai/objectstack#22961 (PR objectstack-ai/objectstack#22996). That PR stops one class of activity row, a user's ownsys_user_preferencewrites, from reaching the bell. It does not touch how the bell renders the rows that remain.What the user sees
On the 2026-10-12 staging walk of the cloud console (objectstack-ai/cloud#2772 item 5; the screenshot is on objectstack-ai/objectstack#22961), each bell Activity row reads
Updated User Preference "ui.recent"with the subtitle… · sys_user_preference. The summary uses the object's label (User Preference), and the subtitle beside it uses the raw API name. Every other activity row renders the same way, so a lead shows· crm_lead.Named site (objectstack-ai/objectui
origin/main9646e2ed)packages/app-shell/src/layout/InboxPopover.tsx: the activity row's second line renders{timeAgo(a.timestamp, displayLocale)} · {a.objectName}.packages/app-shell/src/layout/activityItemType.ts:objectName: String(r.object_name ?? ''), copied verbatim fromsys_activity.object_namewith no label lookup.Expected
The subtitle names the object the way the rest of the console does: by its label, in the reader's locale, which is what the row's own summary already does. The API name is a fallback only when no label resolves.
Dedupe
MCP
search_issuesover objectstack-ai/objectui, open and closed:bell activity tab shows raw object API name object_name instead of object label: 0 hits.InboxPopover activity objectName label machine name crm_lead: 0 hits.inbox notification bell console: 9 hits (inbox popover always opens on the Notifications tab — with 0 notifications and 3 pending approvals the bell shows "3" and the panel says "You're all caught up" #11698, Console: notification bell dropdown always empty while list page / API / inbox tables show unread notifications #4156, app-shell: the inbox tick re-fetches sys_notification_receipt?top=200 in full every 10 s — never incrementally #7392, app-shell: on the console HOME the inbox feed polls every 2 s (sys_inbox_message + sys_notification_receipt top=200) instead of the declared 10 s; realtime is loaded but unused for the bell #7249, REGRESSION: the console header bell panel is dead again — "No notifications" under both Unread and All while/api/v1/notificationsreturns 10 rows (#4110 / #4156 back on console 09987b68) #4230 among them). None is this defect.