Repository navigation
console shell: the page-header star and the sidebar pin become one "Pin to sidebar" action in the page overflow menu, landing in the Pinned section at the top; the app sidebar's bottom Favorites group goes #12427
Description
Filing gate ③, a task the maintainer dispatched in person (chat, 2026-10-15, session session_019YFzJp4o8Ck4NsT1toC4UP, seat account os-bill). The maintainer's words, verbatim: 「用户个人收藏,左侧菜单也有一个 pin 按钮,目前点击pin 会到顶部,但是点击右上角的收藏没有任何效果。包括这个收藏需要保留吗」, then, on the seat's proposal to merge the two into one Pinned section: 「合并为 Pinned 可以,但是这个功能常用吗?需要放在列表页右上角的明显位置吗?你的设计图我也没看到这个按钮」. The design this follows is the prototype at https://claude.ai/artifact/8JLqDFmcuK82RS1Cb8219f (private to the maintainer; the page header's ⋯ menu on the main artboard).
Blocked-by: #12423
Serial after #12423: that card rewrites the same page-header region (PageHeader.tsx, the header call site in ObjectView.tsx) and keeps the star for now; this card removes the star once #12423 has landed, so the two never edit the header in parallel.
Reader who acts: the domain:ui lane, one dev round in @object-ui/app-shell plus the ten @object-ui/i18n packs, after #12423 merges.
Dedupe (MCP search_issues, scope objectstack-ai/objectui, all states, read 2026-10-15T04:58Z): "favorites star pinned sidebar nav pin object page header" → 5 (#7044, #3631, #3999, #1055, #702, all closed; #1055 is the hover rule for the sidebar pin icon and stays in force; #3631 is the pin storage-key observation, closed); "Favorites group sidebar bottom not visible Recent" → 0, a zero read in the same run as the first query's five hits, so the channel was live. None is this card.
The problem
The console has two personal "keep this handy" controls that write the same store and land in different places. The sidebar's pin control writes a type: 'nav' favorite and the item appears in the Pinned section at the top of the app navigation, which the user sees at once. The star at the top right of an object list page (and of a record page) writes a type: 'object' or type: 'record' favorite, and that appears in a Favorites group rendered after the whole navigation tree and after Recent, at the bottom of the sidebar. On an app with a long navigation the group is below the sidebar's viewport, so the star looks dead. For an object that already has a navigation item the two controls express the same wish twice, and the one with the worst feedback is the one in the page header's most prominent slot. Pinning is a once-and-forget action, not a daily one; it does not deserve that slot.
Readings (objectui origin/main fc528c3, read 2026-10-15T04:50Z)
- One store, two buckets:
packages/app-shell/src/context/FavoritesProvider.tsx— localStorage keyobjectui-favoritesscoped per user with write-through to theUserDataAdapterslotui.favorites;FavoriteItem.typeis one of object, dashboard, page, report, record, nav (line 56); the nav bucket and the non-nav bucket are capped separately (130–134). - Sidebar pins:
packages/app-shell/src/hooks/useNavPins.ts45–80 — a pin is atype: 'nav'favorite withpinned: trueand idnav:<navId>;NavigationRendererdraws pinned items in the Pinned section at the top of the app navigation, in the user's order (objectui#12059). - Where the star's favorite lands:
packages/app-shell/src/layout/UnifiedSidebar.tsx— in the app context the Favorites group (favorites.some(f => f.type !== 'nav'), up to 8) is rendered after the navigation tree and after Recent (the block around 565–575); the console-home sidebar has a separate Starred group for object, dashboard and page favorites (653–661). - The star buttons:
packages/app-shell/src/views/ObjectView.tsx1609 (useFavorites) and 3895–3915 (the header button, testidobject-favorite-btn-<object>, idobject:<name>);packages/app-shell/src/views/RecordDetailView.tsx572 (the record page's star). - Other readers of the store:
HomePage.tsx243 (the Home page's favorites);CommandPalette.tsxdoes not read favorites (it reads the app's nav items only). - Measured 2026-10-15T04:48Z, console
fc528c3at 1440×1000 against the HotCRM demo, driven by Playwright: the star flipsaria-pressedto true and a Favorites group appears in the sidebar DOM at y=1244 while the sidebar's scroll viewport spans y=56–1000; nothing changes in view until the sidebar is scrolled to its bottom. localStorage gains{"id":"object:crm_lead","label":"Leads","href":"/apps/app.objectstack.hotcrm/crm_lead","type":"object"}.
What to build
- The star button leaves the object list header and the record page header. In its place the page's overflow menu (the ⋯ next to New and Import that console list page: the toolbar's settings cluster folds into one Display popover, view tabs size to their width and carry the view's type icon, the row-number cell yields to the checkbox on hover, and the page header is one row #12423 keeps in the one-row header) gets one entry, "Pin to sidebar" / "Unpin from sidebar", reflecting the current state. New keys in all ten locale packs.
- Semantics of that entry: when the current app's navigation has an item for this page's target (an
objectitem with thisobjectName, or adashboard/pageitem with this name), it toggles that item's pin through the existinguseNavPins().togglePin, so the result is the Pinned section at the top, the same as the sidebar's own pin control. Otherwise (a record; an object the app does not list) it toggles the existing non-nav favorite, and that group renders directly under the Pinned section at the top of the app sidebar, never after Recent. - The Favorites group at the bottom of the app sidebar is removed; its content is what 2 renders at the top. The console-home sidebar's Starred group and the Home page's favorites are unchanged. The store, its keys and the adapter slot are unchanged; no migration: an existing
object:orrecord:favorite simply renders in the new place. - The sidebar's hover pin control stays the primary way to pin a navigation item (objectui#1055's hover rule unchanged).
Acceptance
- On the Leads list of an app whose navigation lists
crm_lead, "Pin to sidebar" writes onenav:<id>favorite withpinned: trueand noobject:crm_leadfavorite; the Pinned section shows Leads inside the sidebar's visible top; the entry now reads "Unpin from sidebar" and a second click removes the pin. - On a record page, the entry writes a
record:favorite and the group that shows it sits directly under Pinned (in the HotCRM demo at 1440×1000 its label's bounding box lies inside the sidebar's viewport without scrolling), not after Recent. - The list header and the record header render no star button (the
object-favorite-btn-*pins are updated deliberately, not deleted silently);pnpm testfrom the repo root green on the affected files; i18n parity green; a changeset (minor) for every published package touched.
Out of scope
- The Home page and the console-home Starred group; the command palette reading favorites; pin ordering (objectui#12059 landed it).
- Any change to the favorites store shape or to
packages/spec.
Attribution: written by the domain:ui seat in session session_019YFzJp4o8Ck4NsT1toC4UP (account os-bill) on the maintainer's instruction quoted above.
Activity
objectstack-fleet commentedon Oct 15, 2026
Addendum 2026-10-15T04:55Z by the filing seat (
session_019YFzJp4o8Ck4NsT1toC4UP, os-bill), two maintainer follow-ups in the same chat, verbatim: 「之前 pin 是左侧菜单划过的实现显示,你的意思是去掉,换到右上角的下拉菜单?」 and 「如果两个概念合并,那叫收藏是不是更好」, plus a proposal: 「是否建议类似 Claude code,左侧菜单划过时,加上下拉,很多功能可以放进去。比如设计对象等。」Naming (replaces "Pinned" wherever this card says it). The merged section at the top of the app sidebar is called Favorites (zh-CN 收藏), with the star icon; the sidebar label "Pinned" is retired. Reasons: the store is already
favorites, the i18n keyscommon.addToFavorites/common.removeFromFavoritesandsidebar.favoritesalready exist in all ten packs, the Home page and the console-home sidebar already call the same items favorites, and "pin" describes a position while this feature is a personal collection that happens to be shown at the top (Notion and Linear name the same section Favorites).type: 'nav'stays an internal storage detail; nothing in the store changes. The sidebar's hover control therefore becomes a star, not a pin icon, and the page overflow entry reads "Add to favorites" / "Remove from favorites".Where the control lives (answering the first question). The sidebar's hover-revealed control stays and stays primary; what goes is only the always-visible star in the page header. The page overflow entry is the same action for pages that have no sidebar item to hover (records; objects the app does not list).
Scope extension (the proposal; same files, same card). The hover-revealed control on a sidebar navigation item becomes a small ⋯ menu (also opened by right-click), and the star joins it as its first entry instead of being its own icon. Entries derive from the item's type, never from a product (ADR-0060): "Add to favorites" / "Remove from favorites"; "Open in new tab"; "Copy link"; and, only for a principal who may author metadata (
isAdmin && canAuthorMetadata, the gatePageView.openInStudioalready uses), a "Design" entry that opens the item's designer: apageitem goes to/apps/APP/metadata/page/NAMEexactly asPageView.tsx129–132 does today, anobjectitem to the object designer, adashboarditem to the dashboard designer (the dev finds each route in the console's metadata-admin router rather than from this comment). Items with no designer (url,component,separator) show no Design entry. The menu is one shared component for all item types; objectui#1055's rule (hover only, nothing permanently visible) carries over to the ⋯ trigger.Acceptance adds: hovering a nav item shows one ⋯ trigger and no standalone pin icon; the menu for an
objectitem lists exactly the four entries above for an admin and three for a non-admin; "Design" on the Leads item of the HotCRM demo lands on the object designer forcrm_lead; right-click opens the same menu.Reading time 2026-10-15T04:55Z.
objectstack-fleet commentedon Oct 15, 2026
Claim: PM loop round 2
Session:
session_019YFzJp4o8Ck4NsT1toC4UPAccount:
os-bill(the seat's linked user asGET /useranswers it; always the card's assignee)Branch:
claude/issue-12427-favorites-sidebar-menuWorktree:
objectui-issue-12427Domain:
domain:uiSeat:
domain:ui#3File surface:
packages/app-shell/src/layout/UnifiedSidebar.tsx(the Favorites group, the hover control, the new per-item ⋯ menu and its wiring), one new shared menu component underpackages/app-shell/src/layout/orcomponents/with its tests,packages/app-shell/src/hooks/useNavPins.tsandpackages/app-shell/src/context/FavoritesProvider.tsx(readers only unless a read helper is missing; the store shape is frozen),packages/app-shell/src/views/ObjectView.tsxandpackages/app-shell/src/views/RecordDetailView.tsx(the page-header overflow entry only; see the serial note below),packages/i18n/src/locales/*.ts, one.changeset/12427-*.md(stop on breach; explain in the report)Container & model:
M — one new shared menu component plus two header call sites and a sidebar group move; design judgment in the menu's entries per item type, not mechanical,mode:subagent,model: TIER_DEFAULT (opus) — read from scripts/pm/dispatch-gates.data.mjs at objectstack 16abea8 (TIER_DEFAULT = opus, TIER_FLOOR = sonnet); the sister-repo --tier verdict with explicit paths refuses in this checkout with MODULE_NOT_FOUND (objectstack node_modules absent), so the constants file is the reading; ceiling CONTRACT_REVIEW_TIER not reached: no MANDATORY_TIER_GLOB_ROWS path on this surfaceClause-②: yes
Responsibility:
n/a — not a defect cardThread-read: 6184739946
Serial constraints cleared:
domain:uiin-flight claims read 2026-10-15T06:52Z — objectui#12433 (plugin-detailrecord:detailssections,sunhaolin): disjoint surface; objectui#12423 (this seat): its PR #12436 is ACCEPTed with a contract-review PASS,mergeable_stateclean, and waits only on the maintainer's ready + auto-merge click; it editsObjectView.tsx(the header actions where this card's overflow entry goes) and nothing else on this surface. Handled by ORDER, not by waiting: the dev builds the sidebar half first and touchesObjectView.tsx/RecordDetailView.tsxonly afterorigin/maincarries #12436 (the merge check is in the dispatch brief); not there when reached ⇒ stop and reportblocked. Same-day merges on the surface, all onorigin/main6fcb2cealready: 6fcb2ce (#12437, app opens on the first shown navigation entry), 63079f4 (#12430), 4b0a087 (#12414). No queued sibling shares a hot file; objectui#12429 (sidebar collapse toggle,pm:blockedon this card) and objectui#12440 (tab strip into the list toolbar, blocked on #12423) are serial behind.Resume-from: none
Blocked-by #12423 is lifted for dispatch on the maintainer's word in chat (2026-10-15, verbatim: 「你可以继续开发」) after the seat reported that #12436's landing stroke was refused by the container's classifier; the overlap is handled by order as above, and the card's own text stands with its addendum (comment 6184739946: Favorites naming, the sidebar item's ⋯ menu with the Design entry).
Maintainer direct-dispatch channel, verbatim authorisation (chat, 2026-10-15): 「按这个方案在 objectui 开一个 issue,使用 dispatch 技能,然后你负责派发开发。」 and the follow-ups quoted in the card and its addendum. Routing (
domain:ui,area:devpath,priority:p2) was written by this seat under that channel; triage may regrade.Reading time 2026-10-15T06:55Z.
objectstack-fleet commentedon Oct 15, 2026
os-dev-report
{
"issue": 12427,
"status": "blocked",
"branch": "claude/issue-12427-favorites-sidebar-menu",
"pr": "#12443",
"session": "session_019YFzJp4o8Ck4NsT1toC4UP — the Claude-Session id this subagent was stamped with (the parent seat's)",
"premise_still_valid": true,
"summary": "Neither half is complete. What landed is the in-surface groundwork, at adb45f8 in draft PR #12443 (body starts 'Part of #12427'). That is SidebarItemMenu (packages/app-shell/src/layout/SidebarItemMenu.tsx, with 15 tests), the one per-entry ⋯ menu for every entry type: Add/Remove favorites; Open in new tab and Copy link under the router basename, with an off-console URL used verbatim; Design for object/dashboard/page entries, gated isAdmin && canAuthorMetadata and routed to /apps/APP/metadata/TYPE/NAME; hover-only trigger; right-click opens it. Six new console.nav keys in all ten packs, and a minor changeset. BLOCKED 1, file surface: the hover pin control and the top Favorites section are not in UnifiedSidebar.tsx. NavigationRenderer in packages/layout/src/NavigationRenderer.tsx (@object-ui/layout) draws both: the pin is the SidebarMenuAction with the Pin/PinOff icon and the console.nav.pinItem label, and the section is its favoritesSection. No prop lets a host replace the per-row control or add rows to that section. The claim says stop on breach, so that file is untouched and UnifiedSidebar.tsx is unchanged (wiring the menu, merging the non-nav favorites to the top and deleting the group after Recent all need the layout slot). BLOCKED 2: #12436 is not yet on origin/main. The grep for 'No favorite star here since objectui#12423' on origin/main ObjectView.tsx printed 0 at 431cece; the control on the PR head 4ba299c printed 1. ObjectView.tsx and RecordDetailView.tsx are untouched. Premise note: on main the top section is already titled Favorites (console.nav.favorites, 收藏, star icon). Only the hover control still says pin.",
"tests": "At adb45f8. (1) pnpm exec vitest run packages/app-shell/src/layout/tests/SidebarItemMenu-12427.test.tsx printed 'Tests 15 passed (15)'. The tests cover: object entry shows four entries to an admin who may author metadata (Design last), three to a non-admin and three to an admin without manage_metadata; Design navigates to /apps/crm/metadata/object/crm_lead; the favorites entry reads 'Remove from favorites' and toggles once; Open in new tab calls window.open('/_console/apps/crm/crm_lead','_blank','noopener,noreferrer'); Copy link writes the origin plus /_console/apps/crm/crm_lead; an off-console URL is used verbatim; a url entry has no Design; an action entry shows only the favorites entry; right-click opens the menu with the default prevented; sidebarItemDesignPath for page/object/dashboard, and null for url/component/separator. (2) pnpm exec vitest run packages/i18n/ (with the menu test) printed 'Test Files 84 passed (84)' and 'Tests 1336 passed | 13 skipped (1349)'. A verbose rerun of all-locales-key-parity, en-zh-key-parity and the menu test printed '63 passed (63)'. (3) pnpm --filter @object-ui/i18n --filter @object-ui/app-shell run type-check: VERDICT command-exit 0. It ran after building app-shell's dependency closure ('Tasks: 28 successful, 28 total'), and tsc -p tsconfig.test.json --listFilesOnly lists both new files. (4) Two ablations through objectstack scripts/ablation-replace.mjs; the test imports the source, so no dist is involved. Dropping canAuthorMetadata from the Design gate (anchor 1 to 0, blob 045e33c to d2ff3d7) failed exactly one test, 'lists exactly three for an admin the server refuses metadata authoring'. Dropping the absolute-URL test from offConsole (blob 045e33c to a5e449c) failed exactly one test, 'an external entry opens and copies its URL verbatim'. Each run was restored to the HEAD blob 045e33c with git diff HEAD empty. The first run of the menu test found a real bug (an absolute url entry without target was joined under the basename), fixed before commit.",
"gates": "Local subset. All were run before any pipe and all exited 0: check:i18n-keys, check:i18n-dead-keys, check:i18n-drift ('6 key(s) added, 0 removed'), check:vi-mock-specifiers, check:vi-mock-inherit, check:vi-mock-override-shape, check:new-line-citations, check:control-bytes, check:test-path-roots, node scripts/check-changeset-presence.mjs ('12 source file(s) of 2 released package(s) changed, and this change declares 1 changeset'), and node scripts/check-changeset-no-major.mjs. objectui has no dispatch-gates.mjs, so there is no --ran reconciliation. I derived this list by hand from package.json check:* and the files the diff touches: locales, a test with vi.mock, new source, a changeset. CI check-runs on adb45f8 (36), read once at report time without polling: success for Changeset Bump Policy, Changeset Declaration, Changeset Fixed Group Check and label; skipped for Test (coverage), Test (coverage shard), dependabot; in_progress for Type Check, Lint, Repo Gates, Line Citation Gate, Governed Surface Queue Guard, Test (shard 1-16 of 16), Test (dist pins), Build & E2E, Build Docs, Bundle Analysis, Changeset Claim Re-read, Changeset Overwrite Report, Spec Main Shape Gate and Live E2E. CI convergence is the seat's.",
"mcp_calls": "0 — no MCP GitHub tool was called",
"api_writes": "2 relay dispatches, each POST /repos/objectstack-ai/objectstack/dispatches. One was pr_create: the relay ran POST /repos/objectstack-ai/objectui/pulls (draft) and then POST /repos//issues/12443/assignees with os-bill; the read-back was 6826 of 6826 bytes, identical. The other is this os-dev-report comment, which the relay posts as POST /repos//issues/12427/comments. Two git pushes went outside REST: the empty-branch probe and adb45f8. No label writes: the brief named none, and the objectui labeler owns path labels.",
"open_questions": [
{
"question": "The sidebar half needs packages/layout/src/NavigationRenderer.tsx, which is outside the claimed surface. How should the next round get it?",
"options": [
"A: extend the surface to NavigationRenderer.tsx plus one layout test. Add two generic additive props: a per-row slot the host fills, drawn in place of the pin action, and host rows appended inside the Favorites section, which then renders when either kind of row exists. Hosts passing neither keep today's behaviour. The existing tests that click 'Pin NAME' by name are updated deliberately: UnifiedSidebar.pinnedOrder-12059.test.tsx, navItemVisibleEvaluated.test.tsx and the layout pin tests. Size S-M; resume from this branch.",
"B: UnifiedSidebar draws the whole Favorites section itself and NavigationRenderer's section is switched off. This still needs a layout prop and an export of PinnedNavigationList, or else it loses the objectui#12059 drag order, so it is a bigger surface and duplicates rows.",
"C: re-scope so that this card only moves the non-nav group, and the ⋯ menu goes to a later card. This is not workable either: merging into the top section needs the layout's favorites slot anyway."
],
"recommendation": "A, because it is the smallest generic change, keeps one renderer and the pinned drag order, and SidebarItemMenu on this branch already fits it as is."
},
{
"question": "Should Design also appear on report and doc entries? The metadata-admin router serves metadata/report/NAME and metadata/doc/NAME with editors, but the addendum names only page, object and dashboard.",
"options": [
"A: keep the three the addendum names (the branch does this)",
"B: add report, and maybe doc"
],
"recommendation": "A. It stays inside the addendum's enumeration, and adding a type later is one line in sidebarItemDesignPath plus one test."
},
{
"question": "Two dashboard designers exist: metadata/dashboard/NAME, the metadata-admin router, and design/dashboard/NAME, DashboardDesignPage, which no in-tree link points at. Which one should Design open?",
"options": [
"A: metadata/dashboard/NAME (the branch does this)",
"B: design/dashboard/NAME"
],
"recommendation": "A, because the brief says to use the metadata-admin router and it is the route PageView already uses for pages."
},
{
"question": "The merged section's title and the labels of non-nav rows are not decided.",
"options": [
"A: title the merged section with console.nav.favorites (already Favorites / 收藏 with a star). A record or object favorite row shows its stored label (refreshLabel self-heals it) with a type icon, as the bottom group does today, and carries the same ⋯ menu, where the toggle removes it. Design shows for object, dashboard and page favorites (derived from the id), never for record or report. sidebar.favorites becomes unread and is deleted from ten packs; sidebar.removeFromFavorites stays for the console-home Starred group.",
"B: resolve non-nav labels live, as useRecentItemLabel does"
],
"recommendation": "A. There is no store change and no migration, and the labels match what Home shows."
},
{
"question": "On mobile, enablePinning is off today, so there is no hover control. Should the ⋯ menu also be absent on mobile?",
"options": [
"A: absent on mobile, the same as today",
"B: always visible on mobile"
],
"recommendation": "A. It keeps the objectui#1055 hover-only rule and today's mobile behaviour."
}
],
"out_of_scope_findings": []
}
objectstack-fleet commentedon Oct 15, 2026
Scope note 2026-10-15T07:25Z from the dispatching seat (
session_019YFzJp4o8Ck4NsT1toC4UP, os-bill) on the dev report 6186752694 (status blocked, draft PR #12443 atadb45f8). The stop was right: the claim's surface did not reach the file that draws the control. Five decisions; the dev reads them with the card, the addendum and the claim.packages/layout/src/NavigationRenderer.tsxand one new test underpackages/layout/src/__tests__/, with@object-ui/layout(published; noprivatekey) added to the changeset as minor. Readings at this writing (2026-10-15T07:25Z): the governed-surface guard answers NOT GOVERNED for the path; noorigin/maincommit has touched the file since 2026-10-14; no in-flightdomain:uiclaim names it. Shape = the dev's option A: two additive props onNavigationRendererProps— a per-row slot the host fills, drawn in place of the pinSidebarMenuAction(lines 1559–1577 and 1625–1643 onorigin/main), and host rows appended insidefavoritesSection(line 1762), which then renders when either kind of row exists. A host passing neither keeps today's behaviour, the pinned drag order (objectui#12059) included. The existing tests that click "Pin NAME" by name are updated deliberately, as the report lists them.metadata/dashboard/NAME. Report and doc entries get no Design entry on this card.console.nav.favorites(already Favorites / 收藏 with the star onmain). A non-nav favorite row shows its stored label (the store'srefreshLabelself-heals it) with its type icon, carries the same ⋯ menu, and its favorites entry removes it; Design shows for object, dashboard and page favorites derived from the id, never for a record or report favorite.sidebar.favoritesbecomes unread and leaves all ten packs;sidebar.removeFromFavoritesstays for the console-home Starred group. The Favorites group drawn after Recent inUnifiedSidebar.tsx(the block around lines 524–530) is removed.enablePinningis off today; the objectui#1055 hover rule and today's mobile shape stand.ObjectView.tsxandRecordDetailView.tsxonly onceorigin/maincarries feat(list): Filter · Sort · Display · Search toolbar, width-fitted view tabs, one leading row cell, one-row page header #12436 (the same grep; feat(list): Filter · Sort · Display · Search toolbar, width-fitted view tabs, one leading row cell, one-row page header #12436 has been in the merge queue since 2026-10-15T07:18Z with the queue CI running). Reached with 0 ⇒ the PR staysPart of objectstack-ai/objectui#12427and the report says blocked on that one item; nothing else waits on it.Resume-from:
claude/issue-12427-favorites-sidebar-menu@adb45f8— same worktree, same branch, same draft PR #12443. When both halves are in, the PR body's first line becomesFixes objectstack-ai/objectui#12427(relayissue_patchon the pull's number, body otherwise kept) and the seat re-reads it before ready.Thread-read: 6186752694
Generated by Claude Code
objectstack-fleet commentedon Oct 15, 2026
os-dev-report
{
"issue": 12427,
"status": "blocked",
"branch": "claude/issue-12427-favorites-sidebar-menu",
"pr": "#12443",
"session": "session_019YFzJp4o8Ck4NsT1toC4UP — the Claude-Session id this subagent was stamped with (the parent seat's)",
"premise_still_valid": true,
"summary": "Resumed from adb45f8 under scope note 6186841419. The head is 0bc0189, draft PR #12443, still 'Part of #12427'. LANDED, sidebar half: NavigationRenderer gets two additive props. renderItemAction is a host control drawn on every leaf and action row in place of the pin action. extraFavorites are host rows appended inside the Favorites section, which renders when either kind exists. A host passing neither keeps today's behaviour, drag order included. UnifiedSidebar fills the slot with SidebarItemMenu: one hover-revealed ⋯, right-click opens it, the favorites entry toggles through useNavPins().togglePin, Design shows for object/dashboard/page via metadata/TYPE/NAME, and there is no trigger on a phone. The non-nav favorites become rows of the top section with the same menu (the toggle removes them; Design comes from object:/dashboard:/page: ids). The group after Recent is gone, sidebar.favorites leaves the ten packs, and the store is untouched. LANDED, header half: #12436 reached origin/main (the grep printed 1 at a2225f9) and was merged in with a merge commit. The list header's actions row now ends with an icon-only ⋯ (named by the existing detail.moreActions key) holding the shared FavoriteMenuItem. useObjectListFavorite pins the app's own object nav entry when the member's shown navigation has one: one nav:ID with pinned true and no object: favorite. Otherwise it keeps object:NAME. The record page's overflow leads with sys_favorite (record:), ahead of Share. BLOCKED on ONE item: the record header still draws its star. RecordTitleChip draws it from the page:header renderer in packages/components/src/renderers/layout/containers.tsx, which is outside the surface. showStar defaults to true from the schema alone. If RecordDetailView stopped passing isFavorite/onToggleFavorite, the star would stay and store nothing (probe: one 'Add to favorites' button, aria-pressed false). So the wired star is kept, and the PR stays 'Part of'. CI on 0bc0189: 34 success, 3 skipped.",
"tests": "At 0bc0189. NEW: SidebarItemMenu-12427 (15); NavigationRenderer.hostItemAction-12427 (8): slot in place of the pin, context href/external/label, no slot on group/separator, drawn with pinning off, host rows after pinned rows, null/false/[] count as none, default kept; UnifiedSidebar.favoritesMenu-12427 (10): one ⋯ and no pin per row, 4 entries for an admin and 3 for a non-admin, right-click, Add writes one nav:nav_leads pinned and then reads Remove, no trigger at 375px, stored object:/record: favorites in the top section with localStorage byte-identical, group labels exactly ['Favorites','Recent'], one section for pin plus stored favorite, Design on an object favorite and not on a record, Remove removes; ObjectView.favoritesEntry-12427 (3): no star button and the last control is an icon-only 'More actions', one nav:nav_projects (type nav, pinned true) and no object:, then 'Remove from favorites', then [] after the second press, object:showcase_project with label Projects and href /apps/demo/showcase_project when unlisted; RecordDetailView.favoritesEntry-12427 (2): overflow [Add to favorites, Share, ...], writes record:crm_call:rec-call-1 and then reads Remove. UPDATED deliberately: UnifiedSidebar.pinnedOrder-12059 drives the ⋯ menu ('More actions for NAME', then Add/Remove) instead of 'Pin NAME'; the starred record now reads '📋Acme' after the pinned rows. navItemVisibleEvaluated and the layout pin tests drive NavigationRenderer without the slot and pass unchanged. ABLATIONS (ablation-replace, each landed and was restored to the HEAD blob, git diff HEAD empty): leaf slot replaced by null, 8 red; hasExtraFavorites=false, 6 red; useObjectListFavorite's 'if (entry)' made false, 1 red ('writes one nav pin and no object favorite...'). UNION on 0bc0189: packages/layout/ + packages/app-shell/src/layout/ + packages/i18n/ + 24 other tests naming UnifiedSidebar/NavigationRenderer/SidebarItemMenu gave 'Test Files 218 passed (218)' and 'Tests 2512 passed | 13 skipped (2525)'. The RecordDetailView* and ObjectView* prefixes gave 'Test Files 124 passed (124)' and 'Tests 961 passed (961)'. TYPE-CHECK: pnpm --filter layout/i18n/app-shell run type-check, VERDICT command-exit 0, after rebuilding app-shell's closure (28/28; layout dist .d.ts carries renderItemAction). The test tsconfigs list the new tests (layout 1, app-shell 5). CI FIX: on head 122909d, Test (shard 5/16) failed objectView-config-keys-retired-4730.test.ts 'the namespace root survives, with the same surviving key shape in every pack': expected [ 'moreActions', …(102) ] to have a length of 102 but got 103. That was my new console.objectView.moreActions key. Fixed in 0bc0189 by dropping the key from all ten packs and naming the list ⋯ with the existing detail.moreActions (the record header's ⋯ name). No key was added and the ledger is untouched. That file alone: 5 passed; packages/i18n/: 85 files, 1331 passed and 13 skipped. CI shard 5/16 on 0bc0189 is success.",
"gates": "Local, on the final diff, all run before any pipe and all exit 0: check:i18n-keys, check:i18n-dead-keys, check:i18n-drift, check:vi-mock-specifiers, check:vi-mock-inherit, check:vi-mock-override-shape, check:new-line-citations, check:control-bytes, check:test-path-roots, check-changeset-presence ('21 source file(s) of 3 released package(s) changed, and this change declares 1 changeset') and check-changeset-no-major. objectui has no dispatch-gates.mjs, so there is no --ran reconciliation; I derived the list by hand. CI check-runs on 0bc0189 (37), read once: 34 success (Type Check, Lint, Repo Gates, Line Citation Gate, Governed Surface Queue Guard, Test shards 1-16 of 16, Test, Test (dist pins), Build & E2E, Build Docs, Bundle Analysis, the five Changeset checks, Spec Main Shape Gate, Live E2E, label), 3 skipped.",
"mcp_calls": "0 — no MCP GitHub tool was called",
"api_writes": "This round: 1 relay dispatch, POST /repos/objectstack-ai/objectstack/dispatches, for the os-dev-report comment (POST /repos//issues/12427/comments). No PR body PATCH; see the open question. 3 git pushes, outside REST: 6d2dfc2, 122909d, 0bc0189 (the last one includes 2b1006d), with merge commits 97a9d97 and 61dcd99, and no force-push. Earlier round: 2 dispatches (pr_create with assignees, and report comment 6186752694).",
"open_questions": [
{
"question": "Removing the record header star needs packages/components/src/renderers/layout/containers.tsx, which is outside the extended surface. How should the last acceptance item be closed?",
"options": [
"A: extend the surface to containers.tsx plus one components test. The page:header record chrome draws the star only when RecordContext carries onToggleFavorite (a star with no host toggle stores nothing). RecordDetailView drops isFavorite/onToggleFavorite, and the star's absence is pinned. The overflow entry is already in place. Size S; resume from 0bc0189.",
"B: RecordDetailView sets showStar:false on the page:header nodes of the page it renders. This rewrites authored metadata at render time and fights an author's explicit showStar.",
"C: keep the record star beside the overflow entry. This contradicts the card."
],
"recommendation": "A, because it is one generic condition in the renderer, it removes the dead-star case for every host, and it leaves the authored showStar key meaning what it says."
},
{
"question": "There is a conflict between the dispatch and os-dev.md on the PR body. The resume message and the scope note ask the dev to rewrite the PR body via relay issue_patch. os-dev.md says the dev writes the body once at pr_create and never PATCHes it; later changes are written by the seat. The body on #12443 still describes the stopped first round.",
"options": [
"A: the seat applies the replacement text I prepared at /tmp/claude-0/-home-user/b989e4d2-1086-5f1b-84ed-e7af367b27dd/scratchpad/issue-12427/12427-pr-body-v2.md (6429 bytes, first line 'Part of #12427', 'Clause-②: yes', no angle brackets, no closing keyword near another number)",
"B: the dev patches it in a later round under an explicit exception"
],
"recommendation": "A, because os-dev.md says it wins where the two conflict. I did not PATCH."
},
{
"question": "Which navigation entry does the list header pin when several match?",
"options": [
"A (implemented): the first object entry with this objectName and no recordId, in the member-shown tree, areas in order and then app.navigation. A pin on an entry in an area other than the sidebar's active one does not draw until that area is active, as for sidebar pins today.",
"B: prefer the entry whose viewName matches the open view"
],
"recommendation": "A, because it is the plain reading of the card; B can come later if views get separate entries."
},
{
"question": "Mobile: the non-nav favorite rows had an always-visible remove star below md. They now carry the ⋯ in the same place. Navigation rows get none, per decision 4. Keep that?",
"options": [
"A: keep it, so the phone keeps a way to remove a favorite from the sidebar",
"B: no ⋯ on any row on a phone"
],
"recommendation": "A, because it preserves today's mobile control and decision 4 names only the rows that enablePinning governs."
}
],
"out_of_scope_findings": [
"carrier: objectui#12427 (its record-star item, open question 1) · RecordTitleChip, through the components page:header record chrome, draws a favorite star whenever schema showStar is not false. With no host onToggleFavorite it keeps the state locally and stores nothing. Measured once: the console record page passes the toggle, so the console itself is not dead today. Noted, not filed."
]
}
objectstack-fleet commentedon Oct 15, 2026
Seat verdict ACCEPT (Part of) on PR #12443 (head
0bc0189c273ca6ad700ade586dee73379fc184c3), written 2026-10-15T08:22Z: #12443 (comment). Contract review PASS on the same head: comment 6187751089. Governed-merges audit: not governed, 1,764 lines, ordinary queue. The PR body was replaced with the dev's prepared text by the seat (relayissue_patch). Remainder on this card after the merge: the record header star (@object-ui/componentspage:headerchrome,containers.tsx), shape = option A of report 6187632953; the card returns topm:queueatpriority:p1in the landing stroke. Landing: ready + auto-merge next.Thread-read: 6187632953
Generated by Claude Code
objectstack-fleet commentedon Oct 15, 2026
Landing 2026-10-15T08:38Z: PR #12443 MERGED (
Part of). Two readings, both taken after the merge event:merged: true,merged_at2026-10-15T08:37Z, merged byobjectstack-fleet[bot]out of the merge queue; head0bc0189c273ca6ad700ade586dee73379fc184c3; merge commita8e5b736456d5d9e8fc432f6deff05fc1b2c7c90origin/maina8e5b73"feat(app-shell): the sidebar entry's ⋯ menu, one component for every entry type (part of objectui#12427) (#12443)";packages/app-shell/src/layout/SidebarItemMenu.tsxpresent;renderItemActioninpackages/layout/src/NavigationRenderer.tsx(13 hits);.changeset/12427-sidebar-item-menu.mdpresent, awaiting the release PRDelivered by that PR: the sidebar's per-entry ⋯ menu (favorites, open in new tab, copy link, Design for metadata authors; right-click opens it; none on a phone), one Favorites section at the top with the non-nav favorites as rows after the pinned entries and the group after Recent removed, the two additive
NavigationRendererprops, the list header's ⋯ with the favorites entry (pinning the app's own navigation entry when the member is shown one), the record page's overflow favorites entry, sixconsole.nav.*keys in ten packs andsidebar.favoritesretired.Remaining on this card (one acceptance item): the record header still draws its star, because
@object-ui/components'page:headerchrome (packages/components/src/renderers/layout/containers.tsx,RecordTitleChip,showStardefaulting on) draws it whether or not the host wires a toggle. Shape, per the contract review on PR #12443 (comment 6187751089, ③) and the dev's report 6187632953 option A: the chrome draws the star only whenRecordContextcarriesonToggleFavorite;RecordDetailViewdrops itsisFavorite/onToggleFavoriteprops (its overflow entry already carries the action); the star's absence is pinned in a components test and the existing record-star pins are updated deliberately. Size S;@object-ui/componentsjoins the changeset (minor). Branch fromorigin/main; noResume-from.Status change in this stroke, on the maintainer's word (chat 2026-10-15: 「那后续的任务你放回队列,按 p1 标记」):
pm:dispatched→pm:queue,priority:p2→priority:p1, assignee cleared; the lane's next seat dispatches the remainder. Parent objectstack-ai/objectstack#25945 records the merge. The maintainer's post-merge acceptance (screenshots against the design reference) follows separately.Thread-read: 6187766259
Generated by Claude Code
objectstack-fleet commentedon Oct 15, 2026
Claim: PM loop round 1 (the remainder after PR #12443, as the landing note
6188037096hands it to the lane's next seat;priority:p1)Session:
session_01JZnppgHRp4sREcouhkQYDBAccount:
sunhaolinBranch:
claude/issue-12427-record-starWorktree:
objectui-issue-12427Domain:
domain:uiSeat:
domain:ui#1File surface:
packages/components/src/renderers/layout/containers.tsx(thepage:headerrecord chrome'sshowStar/RecordTitleChipwiring,:1575and:2533–:2545onmaina8e5b73) and one components test;packages/app-shell/src/views/RecordDetailView.tsx(theisFavorite/onToggleFavoritepass-through at:3455–:3456only) and the existing record-star pins it updates; one.changeset/12427-*.md(stop on breach; explain in the report)Container & model:
S,mode:subagent,model: opus(default tier;dispatch-gates --tier --repo objectstack-ai/objectuinames no path-derived mandate)Clause-②: no
Responsibility: n/a — not a defect card
Thread-read: 6188037096
Serial constraints cleared: read at objectui
maina8e5b73.Predecessor: PR feat(app-shell): the sidebar entry's ⋯ menu, one component for every entry type (part of objectui#12427) #12443 (this card's first part) landed as
a8e5b73.Same file, different region: seat 2's objectui#12442 edits
RecordDetailView.tsx'ssynthPartssections derivation (:2796), not the favorite pass-through at:3455. This follows the parallel rule the maintainer's 「12429 为什么不能并行?」 set for a same-file, different-region pair: branch fromorigin/main, mergeorigin/mainonce more before opening the PR, and whichever of the two lands second mergesmainagain (a merge commit, never a rebase).Disjoint: seat 2's objectui#12429 (
UnifiedSidebar.tsx,AppHeader.tsx) and objectui#12440 (ListView.tsx,ObjectView.tsx), and this seat's objectui#12418 (ObjectView.tsxhandlers, user-state wiring).The shape carried: option A, as the contract review on PR feat(app-shell): the sidebar entry's ⋯ menu, one component for every entry type (part of objectui#12427) #12443 (
6187751089, ③) and the landing note name it. Thepage:headerchrome draws the star only whenRecordContextcarriesonToggleFavorite.RecordDetailViewstops passing its two favorite props, since its overflow entry already carries the action. The star's absence is pinned, and the existing record-star pins are updated deliberately.Accept-set reading: the record chrome stops drawing a star that stores nothing. If the dropped props are part of a published
@object-ui/*type, that is a narrowing:Clause-②: no, and one contract-review-tier review is owed before the queue.Generated by Claude Code
objectstack-fleet commentedon Oct 15, 2026
os-dev-report
{
"issue": 12427,
"status": "done",
"branch": "claude/issue-12427-record-star",
"pr": "#12465",
"session": "session_01JZnppgHRp4sREcouhkQYDB — the Claude-Session id this subagent was stamped with (the parent seat's)",
"premise_still_valid": true,
"summary": "Option A, as ruled: the page:header record chrome (packages/components/src/renderers/layout/containers.tsx) computes showStar as the authored flag AND the RecordContext carrying onToggleFavorite, so a host with no toggle draws no star, and an authored showStar: false still hides it where a host wires one. The two (ctx as any) reads became typed reads. RecordDetailView no longer passes isFavorite / onToggleFavorite to RecordContextProvider (a comment marks why). Its sys_favorite overflow entry from PR #12443 is unchanged and is now the record page's only favorites control. Draft PR #12465 at head 59c861e (fix cb68d1a plus a merge of origin/main cf430cd; objectui#12442 was not yet on main), assignee sunhaolin. PR body line 1 is the card's closing keyword, as the dispatch asked; line 2 is 'Clause-②: no', copied from the claim with no narrowing arm, because A2 measured that no published type member is removed. Measurements: A1 held. On the base the new pin drew one star with no context toggle: 2 red (the no-toggle cases), 3 green. A2: the props went to RecordContextProvider. RecordContextValue (@object-ui/react) keeps both members, as the host opt-in that RecordContext.valueShape.pin lists. RecordDetailView declares no such props. RecordTitleChipProps is unchanged. Nothing widened. A3 held, pinned. A4: RecordDetailView was the only in-tree host wiring a toggle. PagePreview (the metadata editor's record-page preview) wires none and loses a star that stored nothing. plugin-detail recordBinding wires none and wraps only record:* block bodies, never a page:header. No in-tree host wires a toggle after this change, so the CONTROL lives in the components pin. Changeset .changeset/12427-record-header-star.md: @object-ui/components minor, @object-ui/app-shell minor. The worktree was removed after the PR opened.",
"tests": "NEW packages/components/src/tests/page-header-star-host-toggle-12427.test.tsx (5 cases), using the real SchemaRenderer and registry under an English I18nProvider. Each case first asserts the chip h1 'Acme' and its 'Copy record ID' button. Cases: no toggle gives no star; isFavorite but no toggle gives no star; CONTROL: a toggle draws one star 'Add to favorites' with aria-pressed false, and a click calls the host once; CONTROL: isFavorite true reads 'Remove from favorites' with aria-pressed true; authored properties.showStar false with a toggle gives no star. UPDATED deliberately: packages/app-shell/src/views/RecordDetailView.favoritesEntry-12427.test.tsx adds 'the record header draws no star, so the overflow entry is the one favorites control'. It asserts no button named Add to / Remove from favorites while the chip is drawn, that the overflow's only favorites entry is 'Add to favorites', and that there is still no star after choosing it. No other test pinned the header star (git grep over the components, plugin-detail, app-shell views, console and e2e tests). BASE RUN of the new pin at a8e5b73: 'Tests 2 failed | 3 passed (5)'. ABLATIONS via objectstack scripts/ablation-replace.mjs, wrap mode, on the committed cb68d1a; the subjects resolve to src through the root vitest alias, so no dist is involved. (1) containers.tsx '!!ctx?.onToggleFavorite &&' became 'true &&' (anchor 1 to 0, blob 04f5745 to 69a08ac): 'Tests 2 failed | 3 passed (5)', exactly the two no-toggle cases. Restored to the HEAD blob 04f5745, git diff HEAD empty. (2) RecordDetailView.tsx re-adds the two props (anchor 1 to 0, blob b18512c to e3ec47c): 'Tests 1 failed | 2 passed (3)', exactly the new no-star case ('expected [ button ] to have a length of +0 but got 1'). Restored to b18512c, git diff HEAD empty. The first attempt at (2) was a no-op: its replacement contained the anchor, the tool refused because the anchor count stayed at 1, ran nothing and restored. It was re-anchored on the provider's closing bracket. UNION on the final head 59c861e: pnpm exec vitest run from the repo root over 167 files (every test naming page:header, RecordTitleChip or onToggleFavorite, every RecordDetailView* suite, PagePreview*, packages/react/src/context/tests, and the console tests mounting RecordDetailView): 'Test Files 167 passed (167)', 'Tests 3386 passed (3386)', lock VERDICT command-exit 0. The same union on cb68d1a before the merge gave the same counts.",
"gates": "Local subset. objectui has no dispatch-gates.mjs, so I derived the list by hand from package.json check:* and the lint, repo-gates, changeset-guard, changeset-presence and line-citation-gate workflows, for the 7 paths. There is no --ran reconciliation. Every exit code was captured to a file before any pipe. On 59c861e, each exited 0: check:new-line-citations ('0 new citation(s)'), check:control-bytes, check-changeset-no-major, check-changeset-overwrite, check-changeset-presence ('4 source file(s) of 2 released package(s) changed, and this change declares 1 changeset(s)'), check:changeset-claims, check:pending-changeset-literals, check:test-path-roots, check:vi-mock-specifiers, check:vi-mock-inherit, check:vi-mock-override-shape, check-doc-links, check:doc-fences and check:doc-json. check:doc-json first exited 2 on the unbuilt tree ('the strict authoring face is not built'), a missing prerequisite rather than a measurement; it exited 0 after the build. On cb68d1a, after turbo build --filter='@object-ui/console...' --concurrency=2 ('Tasks: 35 successful, 35 total'): pnpm --filter @object-ui/components run type-check exited 0 and pnpm --filter @object-ui/app-shell run type-check exited 0, the latter again on 59c861e; tsc -p tsconfig.test.json --listFilesOnly lists both test files once each. check:eager-closure exited 0: 'Console eager closure is 3079.2 KB gzipped across 69 of 2252 chunks (budget: 3119.4 KB, headroom: 40.2 KB)'. check-governed-queue-guard --test over the 7 paths: NOT GOVERNED. The control-byte self-scan of the 7 files found no match (grep exit 1). CI check-runs on 59c861e, 36 in total, read once at report time without polling: success for Changeset Bump Policy, Changeset Fixed Group Check and label; skipped for Test (coverage), Test (coverage shard), dependabot; in_progress for Test shards 1-16 of 16, Test (dist pins), Type Check, Lint, Repo Gates, Line Citation Gate, Governed Surface Queue Guard, Build and E2E, Build Docs, Bundle Analysis, Changeset Overwrite Report, Changeset Claim Re-read, Changeset Declaration, Spec Main Shape Gate and Live E2E (informational). CI convergence is the seat's.",
"mcp_calls": "5 — all reads: issue_read get (12427), issue_read get_comments (12427), pull_request_read get_comments (12443, for the contract review), pull_request_read get (12465, body read-back and draft state), pull_request_read get_check_runs (12465). No MCP write tool was called.",
"api_writes": "2 relay dispatches, each POST /repos/objectstack-ai/objectstack/dispatches. (1) pr_create: the relay ran POST /repos/objectstack-ai/objectui/pulls (draft) and then POST /repos//issues/12465/assignees with sunhaolin. Its read-back: '9059 byte(s) sent, 9059 stored — identical', and the assignees listed are sunhaolin. (2) This os-dev-report comment, which the relay posts as POST /repos//issues/12427/comments. 3 git pushes went outside REST: the empty-branch probe at a8e5b73, then cb68d1a, then 59c861e (merge commit). No force-push. No label writes: the dispatch named none, and the labeler set the path labels.",
"files_changed": [
"packages/components/src/renderers/layout/containers.tsx",
"packages/components/src/tests/page-header-star-host-toggle-12427.test.tsx",
"packages/app-shell/src/views/RecordDetailView.tsx",
"packages/app-shell/src/views/RecordDetailView.favoritesEntry-12427.test.tsx",
"content/docs/layout/page-header.mdx",
"content/docs/guide/layout.md",
".changeset/12427-record-header-star.md"
],
"line_budget": "n/a — the diff touches no skills/** and no managed ledger",
"deviations": [
"Surface: content/docs/layout/page-header.mdx (the showStar table row) and content/docs/guide/layout.md (the showStar comment in the Schema API fragment) are outside the claim's file surface, which says stop on breach. objectui AGENTS.md #2 asks docs to follow every behaviour change. I took the AGENTS.md side, kept each edit to one line, and named it in the PR body so the seat can drop it.",
"Ablation (2)'s first attempt was a no-op: the replacement contained the anchor, and ablation-replace refused and restored without running. The rerun is the one reported.",
"Trailers: the harness reminder asked for a Co-Authored-By line that carries a model name. objectui AGENTS.md (the model-free pair rule) takes precedence, so both commits end with Claude-Session plus 'Co-authored-by: Claude'. The PR footer uses the session-URL form os-dev.md prescribes, not the harness's form."
],
"open_questions": [],
"out_of_scope_findings": [
"carrier: 承接者:无 · noted, not filed. Two notes; the PR body carries only the first, and the seat may add the second to the PR body's Acceptance notes. (i) @objectstack/spec describes page:header showStar as 'Show the follow (favourite) star beside the record title ...' and does not mention the host-toggle condition this PR adds. This is describe text in the sister repo. (ii) After this PR, no in-tree host wires onToggleFavorite, so in the console an authored showStar has no visible effect either way. It stays live for any host of the published @object-ui/components that wires a toggle. git grep finds no producer writing showStar in objectui (examples, apps) or objectstack (examples, package sources outside the spec's own schema, tests and migration template). Zero pull, so not filed. Dedupe words: showStar, page:header favourite star, onToggleFavorite host toggle."
]
}
objectstack-fleet commentedon Oct 15, 2026
Landed ·
domain:uiseat 1 ·session_01JZnppgHRp4sREcouhkQYDB· 2026-10-15T10:50Zmain5c4deb56abat 2026-10-15T10:49Z. It has one parent,e869e41275, and is an ancestor oforigin/main.5c4deb56abto the accepted head59c861e8e4. The seventh,RecordDetailView.tsx, differs as a blob because objectui#12442's PR fix(app-shell): Studio page seed and slotted preview take the runtime detail sections (objectui#12442) #12467 landed first in another region of that file. Its PR hunks are line-identical onmain: the diffe869e41275..5c4deb56abfor that file equals the PR's own diffcf430cd10..59c861e8e4.Fixes objectstack-ai/objectui#12427. The only issue closed with the merge is this card, ascompleted.page:headerrecord chrome draws its favorite star only where the record context carriesonToggleFavorite. An authoredshowStar: falsestill hides it.sys_favoriteentry in the header's ⋯ overflow, which PR feat(app-shell): the sidebar entry's ⋯ menu, one component for every entry type (part of objectui#12427) #12443 put there. Together with PR feat(app-shell): the sidebar entry's ⋯ menu, one component for every entry type (part of objectui#12427) #12443 (the sidebar entry's ⋯ menu), this completes the card.6188181144, report6189550941, ACCEPT6189607772(on the PR). The Spec Main Shape Gate note6189690660on the PR records that gate's base-red. No contract face applied:Clause-②: no, and no published member was removed.page:headershowStaris declared but no longer reaches a user in the reference console: since objectui#12427 the star draws only where a host wires a favorites toggle, and no host does objectstack#23650:showStar, enforce or remove. It also covers the spec describe text that does not mention the host-toggle condition.pm:dispatchedis removed in the same act as this note. The assignee stays, as the record of who drove it.Generated by Claude Code
fix(components): the record header star draws only where the host wir…