Skip to content

feat(components): page:header stops reading showStar; the host toggle is the one star switch - #12644

Merged
objectstack-fleet[bot] merged 1 commit into
mainfrom
claude/issue-12627-page-header-show-star
Oct 16, 2026
Merged

objectstack-fleet[bot] merged 1 commit into
mainfrom
claude/issue-12627-page-header-show-star

Conversation

@objectstack-fleet

Copy link
Copy Markdown
Contributor

Fixes #12627
Clause-②: no

The consumer half of objectstack-ai/objectstack#23650's ruling (record 6203775759, 「A 退役 showStar (Recommended)」), landing ahead of the @objectstack/spec bump that carries objectstack-ai/objectstack#23781. 18.0.0-next.2 does not carry it; the installed pin is 18.0.0-next.1.

What changed

  • Renderer (packages/components/src/renderers/layout/containers.tsx): the showStar read and its pass to the chip are gone. The star draws exactly where the host's RecordContext carries onToggleFavorite; an authored showStar, on the node or under properties, changes nothing. RecordContextValue.onToggleFavorite is untouched.
  • Registration: the page:header inputs no longer publish showStar.
  • RecordTitleChip (packages/components/src/custom/RecordTitleChip.tsx): the showStar prop is retired. The chip draws its star exactly when onToggleFavorite is passed. Measured: the only caller was the renderer above; hotcrm and objectstack have none. This narrows the package's public face (exported through custom/index.ts), so a contract-review-tier review is owed before the queue.
  • Tests (page-header-star-host-toggle-12427.test.tsx): the CONTROL case 'the authored showStar: false hides the star even when the host wires a toggle' is replaced by: showStar: false on the node and under properties still draws the star where the host wires a toggle; showStar: true in both carriers draws no star without a toggle; the registration publishes no showStar input. Every host-toggle case stays.
  • Parity suite (registry-inputs-spec-parity.test.ts): the settledUpstream row page:header / showStar leaves with the input, and the objectstack#6776 note is updated. A page:header.showStar entry in UNPUBLISHED_EXEMPTIONS covers the installed spec, which still lists the key. It disarms itself: the first installed spec carrying the tombstone makes it dangling and stale, and deleting it is the whole fix.
  • Docs: the showStar rows in content/docs/layout/page-header.mdx and content/docs/guide/layout.md are replaced by one sentence: the favorites star draws where the host wires a favorites toggle, and metadata does not control it.
  • Changeset: .changeset/12627-page-header-show-star-retired.md (@object-ui/components minor; names the chip prop removal as breaking for direct users).

Deviations

  • The parity red was in the REVERSE direction (spec-declared key not published), not the forward one. It is covered by the existing per-key UNPUBLISHED_EXEMPTIONS map, not GLOBALLY_UNPUBLISHED_SPEC_KEYS, because only the former goes red on the bump.

Screenshots

HotCRM account record page at 1280 px, served from this branch's console against a fresh hotcrm backend. The reference console wires no favorites toggle, so the expected picture is no star, unchanged; a DOM probe counted 0 star buttons in both themes.

Test evidence (at 485513c)

  • pnpm --filter @object-ui/components test (full, once): exit 0; Test Files 390 passed, 1 skipped; Tests 3936 passed, 24 skipped.
  • Parity file plus the 12427 file: exit 0, 264 passed. Without the exemption entry the parity file was red on 'page:header publishes every top-level key its spec props schema declares'.
  • Ablations, each red then restored with git diff HEAD empty. Re-arming the old read: 2 red. Ungating the chip star: 4 red. Re-publishing the input: 2 red. Renaming the exemption key, which rehearses the bump: 3 red, including 'every unpublished-key exemption names a key the spec really declares' and 'carries no stale unpublished-key exemption'.
  • @object-ui/components: type-check exit 0, build exit 0; built dist carries no showStar, and passing showStar to RecordTitleChip now fails with TS2322.
  • eslint on the touched files: 0 errors. check-changeset-presence, check:i18n-keys, check:i18n-drift, check:new-line-citations: exit 0.
  • Console tsc --noEmit: not measured locally (plugin closure unbuilt; only module-resolution errors, none on changed lines); left to CI.

Acceptance notes

  • The bump seat deletes UNPUBLISHED_EXEMPTIONS['page:header.showStar'] when the suite names it.
  • objectstack's sdui.manifest.json drops showStar on its next .objectui-sha hop; out of scope here.
  • The Layout section of page-header.mdx still lists the star among the chip's parts without its host-toggle condition (polish, left as is).

Session: https://claude.ai/code/session_01RP9ftxaq1x5KKbvFpDWptn

🤖 Generated with Claude Code

https://claude.ai/code/session_01RP9ftxaq1x5KKbvFpDWptn

… is the one star switch

The renderer read, the pass to RecordTitleChip and the registration input
leave ahead of the @objectstack/spec bump that tombstones the key
(objectstack#23650, landed as objectstack#23781). The chip's own showStar
prop retires too: it draws its star exactly when onToggleFavorite is given.

The CONTROL case that pinned "showStar: false hides the star" is replaced by
pins that an authored showStar (on the node and under properties) changes
nothing, and that the registration publishes no showStar input. The parity
suite's settledUpstream row leaves; a page:header.showStar entry in
UNPUBLISHED_EXEMPTIONS covers the installed spec, and goes dangling and
stale on the bump that installs the tombstone.

Claude-Session: https://claude.ai/code/session_01RP9ftxaq1x5KKbvFpDWptn
Co-authored-by: Claude <noreply@anthropic.com>
@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

席位核对 — ACCEPT · objectui#12627 · head 485513c · 2026-10-16T09:20Z

Seat domain:ui#4, session session_01SJn1GEkrbbBQkhGC26wEDw. Checked against GitHub and the diff, not against the report (relayed on the card, 6212298683). The seat opened this PR from the dev's pr_title_draft and pr_body_draft (degraded channel); the body is the dev's, verbatim.

Checklist

  • Form:
    • Draft → main, assignee os-sales.
    • The first line is Fixes #12627, and the next line is exactly Clause-②: no, matching the claim 6211296171.
    • git merge-tree against current main (726d8c9) is clean. One commit, no PNG on the branch.
  • Sibling: fix(components): the record header draws one primary action, the rest as outline buttons #12635 (objectui#12617, another seat) edits the record header in the same containers.tsx renderer. This diff touches three short spans there: the read, the chip's prop and the registration input. The later lander merges main.
  • Diff, 7 files:
    • containers.tsx: the showStar read and its pass to the chip are gone. The chip still gets onToggleFavorite only when ctx.onToggleFavorite exists, so the host toggle is the one switch. The registration publishes no showStar input, with a comment in the shape the breadcrumb retirement left (objectui#11438).
    • RecordTitleChip.tsx: the showStar prop is retired, and the star draws exactly when onToggleFavorite is passed. That closes the old default where a star drew on local state and stored nothing. The dev measured no other caller, in hotcrm or objectstack either.
    • page-header-star-host-toggle-12427.test.tsx: the CONTROL case the ruling removes is replaced by pins that an authored showStar changes nothing, in both carriers and in both directions. Every host-toggle case stays.
    • The parity suite: the settledUpstream row leaves with the input, and the objectstack#6776 note is updated.
    • Docs: the showStar rows in both docs are replaced by one sentence, with no issue numbers in the prose.
  • Tests:
    • The full @object-ui/components suite passed: 390 files, 3936 tests.
    • The parity file and the 12427 file: 264 passed. Without the exemption entry, the parity file was red on 'page:header publishes every top-level key its spec props schema declares'.
    • Four ablations, each red and then restored to an empty git diff HEAD:
      • re-arming the old read: 2 red;
      • ungating the chip star: 4 red;
      • re-publishing the input: 2 red;
      • renaming the exemption key, which rehearses the bump: 3 red.
    • Passing showStar to the built RecordTitleChip now fails with TS2322.
  • Changeset: @object-ui/components minor, user-facing prose, naming the chip prop removal as breaking for direct users. Minor matches this repo's convention for retirements in the next pre-release (for example 11389-retire-metric-subcaption, 11608-partialschema-retire).
  • Contract faces: Clause-②: no. The card only narrows: the page:header registration input and the exported chip prop leave, and nothing is added. So one contract-review-tier review is owed before the queue. The seat requests it once CI on this head is green, and it is recorded as its own ## Contract review comment.
  • Screenshots: HotCRM's Apex Logistics account at 1280 px, light and dark, on the never-merged claude/issue-12627-evidence (0c71084). The seat read both: the record chip shows the title, the object label and the copy-id icon, and no star. That is the expected picture, unchanged, because the reference console wires no favorites toggle. Sent to the maintainer at 2026-10-16T09:20Z.
  • CI on 485513c: running at this record. Landing waits for green and for the contract review.

Rulings on the open questions, deviations and findings

  1. Degraded channel over the contract's own PR and report writes: A, as dispatched (the relay is refused with 403 in that container).
  2. The parity cover: (A), the UNPUBLISHED_EXEMPTIONS entry, accepted.
    • The dispatch named the forward direction; the dev measured that the red is the reverse direction (a spec-declared key not published). That falsification is a good result.
    • The entry is the existing per-block mechanism and disarms itself. On the bump that installs objectstack#23781's tombstone, specTopLevelKeys subtracts the key, and both the 'names a key the spec really declares' and the 'no stale exemption' checks name the entry. Ablation A4 rehearses exactly that.
    • (B) GLOBALLY_UNPUBLISHED_SPEC_KEYS would never go red, and (C) would hide the entry from both checks.
    • On the four axes: it answers a measured red; it adds no mechanism and dies on the bump; deleting it is the only fix the suite allows; and it adds no gate.
  3. Out-of-scope findings: agreed, not filed. The bump seat deletes the exemption when the suite names it. The page-header.mdx Layout line about "the follow star" is polish.
  4. Deviations: A. These are the model-free trailers per AGENTS.md, the full suite run moved to the background by the harness but read inside the turn, the stale local branch released, and no hooks skipped.

Implemented-by: cloud session session_01RP9ftxaq1x5KKbvFpDWptn, branch claude/issue-12627-page-header-show-star
Reviewed-by: seat domain:ui#4, session_01SJn1GEkrbbBQkhGC26wEDw


Generated by Claude Code

@github-actions

Copy link
Copy Markdown
Contributor

✅ Console Performance Budget

Metric Value Budget
Eager closure (gzip, 70 chunks) 3094.5 KB 3119.4 KB
Main entry chunk (gzip) 73.8 KB 350 KB
Entry file index-FpoS03Px.js —
Status PASS —

The eager closure is every chunk the entry reaches through static imports — what the browser fetches and parses before the app renders. The entry chunk on its own is a small fraction of it.


📦 Bundle Size Report

Package Size Gzipped
app-shell (consoleActionDispatch.js) 0.20KB 0.19KB
app-shell (index.js) 21.19KB 7.76KB
app-shell (runtime-config.js) 22.59KB 7.89KB
app-shell (types.js) 0.01KB 0.04KB
app-shell (urlParams.js) 10.11KB 3.87KB
auth (ActiveOrganizationStorage.js) 27.95KB 10.04KB
auth (AuthContext.js) 0.31KB 0.24KB
auth (AuthGuard.js) 2.07KB 1.00KB
auth (AuthProvider.js) 40.22KB 10.61KB
auth (AuthShell.js) 3.49KB 1.40KB
auth (ForgotPasswordForm.js) 12.21KB 3.45KB
auth (LoginForm.js) 20.39KB 6.02KB
auth (PreviewBanner.js) 0.90KB 0.50KB
auth (RegisterForm.js) 6.72KB 2.24KB
auth (SocialSignInButtons.js) 9.70KB 3.93KB
auth (UserMenu.js) 3.39KB 1.21KB
auth (auth-gate-events.js) 1.62KB 0.83KB
auth (authStyles.js) 5.27KB 1.86KB
auth (createAuthClient.js) 41.19KB 11.12KB
auth (createAuthenticatedFetch.js) 8.54KB 3.46KB
auth (index.js) 3.63KB 1.64KB
auth (invitation-status.js) 1.22KB 0.70KB
auth (org-roles.js) 6.66KB 2.78KB
auth (phone-identifier.js) 1.11KB 0.66KB
auth (types.js) 0.59KB 0.35KB
auth (useAuth.js) 5.30KB 1.02KB
auth (useWorkspaceAdminStatus.js) 11.08KB 4.58KB
collaboration (CommentThread.js) 27.26KB 8.03KB
collaboration (LiveCursors.js) 3.17KB 1.27KB
collaboration (PresenceAvatars.js) 6.28KB 2.60KB
collaboration (PresenceProvider.js) 2.79KB 1.13KB
collaboration (commentAuthorship.js) 1.39KB 0.78KB
collaboration (index.js) 1.93KB 0.85KB
collaboration (useCollaborationTranslation.js) 6.50KB 2.52KB
collaboration (useCommentSearch.js) 1.98KB 0.88KB
collaboration (useConflictResolution.js) 7.75KB 1.86KB
collaboration (useMentionNotifications.js) 1.81KB 0.68KB
collaboration (usePresence.js) 6.33KB 1.84KB
collaboration (useRealtimeSubscription.js) 7.91KB 2.01KB
components (index.js) 598.32KB 144.25KB
core (index.js) 10.18KB 4.04KB
create-plugin (index.js) 27.94KB 9.51KB
data-objectstack (index.js) 248.20KB 69.22KB
fields (index.js) 283.17KB 72.17KB
i18n (LocalizationContext.js) 2.92KB 1.42KB
i18n (builtinAggregateLabels.js) 0.86KB 0.49KB
i18n (currency.js) 2.59KB 1.22KB
i18n (fallbackInterpolation.js) 6.25KB 2.77KB
i18n (i18n.js) 8.87KB 3.64KB
i18n (index.js) 5.52KB 2.39KB
i18n (pickLocalized.js) 9.86KB 3.95KB
i18n (provider.js) 39.35KB 12.88KB
i18n (translateFn.js) 0.20KB 0.18KB
i18n (useDisplayLocale.js) 3.52KB 1.76KB
i18n (useObjectLabel.js) 36.87KB 9.88KB
i18n (useSafeTranslation.js) 7.14KB 2.92KB
layout (index.js) 40.67KB 11.85KB
mobile (MobileProvider.js) 0.92KB 0.49KB
mobile (ResponsiveContainer.js) 0.94KB 0.38KB
mobile (breakpoints.js) 1.51KB 0.70KB
mobile (createOfflineDataSource.js) 5.61KB 1.75KB
mobile (index.js) 1.99KB 0.87KB
mobile (offlineQueue.js) 3.91KB 1.35KB
mobile (pwa.js) 0.97KB 0.49KB
mobile (serviceWorker.js) 1.48KB 0.62KB
mobile (serviceWorkerSource.js) 3.41KB 1.48KB
mobile (useBreakpoint.js) 1.54KB 0.65KB
mobile (useGesture.js) 6.96KB 1.98KB
mobile (useOfflineSync.js) 1.99KB 0.72KB
mobile (usePullToRefresh.js) 6.62KB 2.45KB
mobile (useResponsive.js) 0.72KB 0.42KB
mobile (useSpecGesture.js) 5.52KB 2.10KB
mobile (useTouchTarget.js) 1.01KB 0.54KB
permissions (MePermissionsProvider.js) 15.35KB 5.51KB
permissions (PermissionContext.js) 0.31KB 0.25KB
permissions (PermissionGuard.js) 0.89KB 0.45KB
permissions (PermissionProvider.js) 6.82KB 2.38KB
permissions (discardProofCache.js) 1.04KB 0.55KB
permissions (evaluator.js) 8.33KB 3.07KB
permissions (index.js) 0.93KB 0.41KB
permissions (store.js) 0.91KB 0.42KB
permissions (useFieldPermissions.js) 1.28KB 0.53KB
permissions (usePermissions.js) 4.83KB 2.27KB
plugin-ai (index.js) 16.04KB 3.92KB
plugin-calendar (index.js) 54.94KB 16.05KB
plugin-charts (index.js) 84.97KB 23.36KB
plugin-chatbot (index.js) 201.89KB 48.13KB
plugin-dashboard (index.js) 146.15KB 39.55KB
plugin-designer (index.js) 233.95KB 50.08KB
plugin-detail (index.js) 262.91KB 69.49KB
plugin-editor (index.js) 2.23KB 1.05KB
plugin-form (index.js) 180.92KB 46.73KB
plugin-gantt (index.js) 178.36KB 45.08KB
plugin-grid (index.js) 265.13KB 73.29KB
plugin-kanban (index.js) 53.23KB 16.71KB
plugin-list (index.js) 129.90KB 33.12KB
plugin-map (index.js) 27.07KB 8.96KB
plugin-markdown (index.js) 13.88KB 4.80KB
plugin-report (index.js) 46.66KB 13.13KB
plugin-timeline (index.js) 39.21KB 11.85KB
plugin-tree (index.js) 15.07KB 5.33KB
plugin-view (index.js) 93.43KB 23.94KB
providers (DataSourceProvider.js) 0.75KB 0.39KB
providers (MetadataProvider.js) 1.37KB 0.59KB
providers (ThemeProvider.js) 1.90KB 0.85KB
providers (UploadProvider.js) 12.07KB 3.68KB
providers (index.js) 0.45KB 0.23KB
providers (types.js) 0.01KB 0.04KB
react-runtime (index.js) 5.62KB 2.34KB
react (LazyPluginLoader.js) 4.47KB 1.63KB
react (SchemaRenderer.js) 120.63KB 39.56KB
react (data-invalidation.js) 5.05KB 2.08KB
react (index.js) 4.50KB 2.06KB
react (schema-input.js) 4.31KB 2.07KB
react (spec-input.js) 0.20KB 0.18KB
sdui-parser (body-dialect.js) 4.50KB 1.99KB
sdui-parser (codegen.js) 9.45KB 3.76KB
sdui-parser (dashboard-widget-options.js) 3.07KB 1.30KB
sdui-parser (index.js) 7.30KB 3.12KB
sdui-parser (input-type.js) 2.84KB 1.40KB
sdui-parser (parse.js) 25.28KB 7.81KB
sdui-parser (provenance.js) 3.84KB 1.90KB
sdui-parser (types.js) 0.29KB 0.24KB
sdui-parser (validate.js) 23.87KB 7.83KB
types (ai.js) 4.39KB 2.17KB
types (api-types.js) 0.20KB 0.18KB
types (app.js) 4.12KB 1.61KB
types (authoring-nodes.js) 0.20KB 0.19KB
types (base.js) 0.20KB 0.18KB
types (blocks.js) 0.20KB 0.18KB
types (cloud.js) 0.20KB 0.18KB
types (complex.js) 4.44KB 2.07KB
types (crud.js) 0.20KB 0.18KB
types (dashboard-filter-alias.js) 6.23KB 2.74KB
types (dashboard-widget-layout.js) 2.06KB 0.96KB
types (data-display.js) 3.75KB 1.85KB
types (data-protocol.js) 0.20KB 0.19KB
types (data.js) 0.20KB 0.18KB
types (designer.js) 1.85KB 0.85KB
types (disclosure.js) 0.20KB 0.18KB
types (error-code.js) 1.54KB 0.88KB
types (expression.js) 0.20KB 0.18KB
types (feedback.js) 0.20KB 0.18KB
types (field-types.js) 1.13KB 0.65KB
types (form.js) 0.20KB 0.18KB
types (http-inflight.js) 8.87KB 3.73KB
types (http-retry.js) 4.32KB 2.02KB
types (icon-key-migration.js) 4.26KB 1.63KB
types (index.js) 5.78KB 2.70KB
types (layout.js) 0.20KB 0.18KB
types (managed-by.js) 0.19KB 0.18KB
types (mobile.js) 5.00KB 2.39KB
types (navigation.js) 0.20KB 0.18KB
types (node-slots.js) 7.18KB 2.34KB
types (objectql.js) 0.20KB 0.18KB
types (overlay.js) 0.20KB 0.18KB
types (permissions.js) 2.52KB 1.31KB
types (plugin-scope.js) 0.20KB 0.18KB
types (record-approval-decision.js) 0.20KB 0.20KB
types (record-components.js) 0.20KB 0.19KB
types (record-panels.js) 0.20KB 0.19KB
types (record-semantics.js) 1.28KB 0.67KB
types (registry.js) 0.20KB 0.18KB
types (reports.js) 0.20KB 0.18KB
types (select-option.js) 0.20KB 0.19KB
types (spec-report.js) 4.99KB 1.96KB
types (spec-ui-namespace.js) 0.20KB 0.19KB
types (strict-authoring-face.js) 19.93KB 7.26KB
types (system-fields.js) 3.33KB 1.54KB
types (theme.js) 6.28KB 2.87KB
types (ui-action.js) 8.48KB 3.50KB
types (views.js) 0.20KB 0.18KB
types (widget.js) 0.20KB 0.18KB

Size Limits

  • ✅ Core packages should be < 50KB gzipped
  • ✅ Component packages should be < 100KB gzipped
  • ⚠️ Plugin packages should be < 150KB gzipped

@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

Contract review

Served-tier: CONTRACT_REVIEW_TIER
Head-sha: 485513cae85b43a4e674ea6938f0a5c1e8dc9e23
Local-runs: none

Inputs read: card objectui#12627 (body and all three comments: first grade 6209085937, claim 6211296171, relayed report 6212298683), the governing ruling 6203775759 on objectstack#23650, PR #12644 (body, 7-file list, git diff origin/main...485513cae after git fetch), and the 36 check-runs on the head (33 success, 3 skipped: dependabot, Test (coverage), Test (coverage shard …); mergeable_state clean). The seat's own ACCEPT on the PR was not an input. Every reading below is a git show / git grep against fetched refs; nothing was built, run or re-run.

① Derived judgments

  1. Renderer read removed — right. PageHeaderRenderer no longer computes showStar; the three-term conjunction (ctx?.onToggleFavorite, schema?.showStar, schema?.properties?.showStar) is deleted and only the explanatory comment names the key. The chip call site still hands onToggleFavorite to RecordTitleChip only when ctx?.onToggleFavorite exists, so the host hook is the one switch. packages/react RecordContext.tsx is not in the diff: isFavorite / onToggleFavorite stay as the host opt-in, exactly what ruling item 2 reserves.
  2. Registration input removed — right. The header registration's inputs no longer carry { name: 'showStar', type: 'boolean' }, with a comment in the shape the breadcrumb retirement left. This is narrowing one: the designer panel and the generated manifest stop offering the key. The new pin the page:header registration publishes no showStar input is non-vacuous (it asserts showCopyId is still published).
  3. Chip prop removed, star gated on onToggleFavorite alone — right and complete. RecordTitleChipProps.showStar and its = true default are gone; the star's draw condition is now onToggleFavorite itself. This is narrowing two (the chip is exported through packages/components/src/custom/index.ts). Callers: git grep RecordTitleChip at the head finds the custom/index.ts export, the containers.tsx import and JSX, and one doc comment in packages/react — no second consumer. hotcrm (fetched HEAD): zero hits for showStar or RecordTitleChip. objectstack origin/main: no import of the chip (one spec doc comment and one regex anti-vacuity fixture in page-header-show-star-retirement.test.ts, which walks only objectstack's own tree). A consequence worth naming: a host that passes isFavorite without onToggleFavorite now gets no star, which the new pin showStar: true … draws no star where the host wires no toggle fixes in place; a badge that cannot be toggled is not something the ruling asked for, so this is right.
  4. No other in-repo caller or published type names showStar — verified. git grep -i showstar over the head tree, lock file excluded: the two source comments, the new test, the parity suite's comment and entry, the two changesets, and packages/components/CHANGELOG.md / packages/layout/CHANGELOG.md history; packages/types has no member; no generated .d.ts or manifest is tracked in objectui with the key; plugin-gantt's showStartEndColumns is an unrelated substring.
  5. Parity suite — right, and the self-disarm claim holds by code reading.
    • The settledUpstream row leaves correctly: that loop asserts, per row, that specTopLevelKeys(type) contains the key AND declaredInputs(type) contains it; with the input gone the second clause reds today, and with the tombstone installed the first would. Removing the row is the only honest move.
    • UNPUBLISHED_EXEMPTIONS['page:header.showStar']: isDormantOnThisPin returns false for any key outside GA_PENDING_UNPUBLISHED_KEYS (seven object-grid.* ids), so the entry is judged live by both every unpublished-key exemption names a key the spec really declares (needs specTopLevelKeys('page:header'), which is authorableShapeKeys with tombstones subtracted, to contain the key) and carries no stale unpublished-key exemption — a published key must lose its entry (needs undiscoverableSpecKeys('page:header') to contain it). On the installed pin (@objectstack/spec@18.0.0-next.1 in pnpm-lock.yaml) the key is live: the dangling check being green on this head is the proof the pin still declares it, and the dev's measured red without the entry is the proof the entry is needed. On the first pin carrying objectstack#23781 (PageHeaderProps.showStar is retiredKey(...), RETIRED_KEYS_BY_MAJOR[18] lists ui/PageHeaderProps:showStar, authorable-surface/ui.json marks it [RETIRED]), authorableShapeKeys drops the key, so the dangling check reds, and undiscoverableSpecKeys drops it, so the stale check reds. Deleting the entry is the whole fix, as its comment says. The reason string carries issue numbers, so states a reason and references a tracking issue passes; it does not start with OWED TO , so the objectui#11111 caps (all 0) are untouched; page:header is not an objectui#8176 lazy block.
    • One correction to the report's reasoning, conclusion unchanged: the global map would not "never self-disarm" — every globally unpublished key is a real spec key on a covered block would also red after the bump, since page:header is the key's only carrier. The global map is wrong for the stated reason in its own comment: it is for a key every block omits for one uniform reason, and "a key whose reason is per-block belongs in UNPUBLISHED_EXEMPTIONS". Likewise the GA-pending list would not hide the entry on this pin: isDormantOnThisPin consults specListedKeys (tombstones included), and every GA-pending exemption arms exactly with the installed spec, all ten together pins that set. The per-key exemption map is the right mechanism.
  6. Tests — right. The CONTROL case the authored showStar: false hides the star even when the host wires a toggle is the only it removed; every host-toggle case stays. Its replacement pins both carriers in both directions and the registration. renderHeader's loosely typed node parameter (a plain string-keyed record) predates this diff and is the honest typing for feeding an off-spec key on purpose; the #0.1 ban is on production literals.
  7. Docs — right, one loose sentence left (③). The showStar rows leave content/docs/layout/page-header.mdx and content/docs/guide/layout.md, including the "false hides it even then" clause, replaced by one sentence stating the host-toggle condition.
  8. Gates. The check-runs on the head are the verdicts: Type Check covers the console tsc the dev could not run locally; Repo Gates, Lint, Line Citation Gate, Governed Surface Queue Guard, Build & E2E, Test (dist pins), all 16 test shards, and the five changeset checks are green.

② Semver level

  • Package set — right. @object-ui/components is the only released package whose source the diff changes; the parity file is a console test and the docs are content/, neither publishes.
  • Level minor — right. This repository's check-changeset-no-major.mjs header states the rule: objectui's own breaking changes ship as minor with the break spelled out in the body, because the major is pinned to the @objectstack major. .changeset/pre.json is mode: pre, tag: next, with no changesets consumed yet and @object-ui/components at 17.7.0 on main, so the entry rides the 18.0.0-next line. Precedents .changeset/11389-retire-metric-subcaption.md and .changeset/11608-partialschema-retire.md are minor. The body names the break ("breaking for direct users") and carries the FROM → TO: a caller that passed showStar={false} stops passing onToggleFavorite. Changeset Bump Policy, Changeset Declaration, Changeset Fixed Group Check and Changeset Overwrite Report are green.
  • Clause-②: no — right. Nothing is added to any published face: two members leave (the registration input and the chip prop) and one authored key becomes inert. The dispatch rule reads a narrowing-only card as Clause-②: no, and the PR body's second line matches the claim 6211296171 exactly. The (narrowing) arm is optional and the spec-side ruling spelled its own half no (narrowing); the bare no is well-formed.

③ Boundary flags

Relayed report 6212298683, every item answered:

  • Open question 1 (who opens the PR and posts the report). The dispatch governs, as taken: the relay was refused in that container, the seat opened the PR from the drafts, and the body is the dev's verbatim. Process only; no effect on the diff.
  • Open question 2 (parity mechanism). The per-key exemption map, as taken; the self-disarm is verified in ① item 5, with the correction to the reasons given against the other two mechanisms.
  • Deviation: core.hooksPath=/dev/null on the evidence branch. The evidence branch is not under review and carries no source; no hooks are configured; no effect.
  • Deviation: model-free commit trailers. The head commit follows objectui's AGENTS.md; not a contract matter.
  • Deviation: the full components suite moved to the background. CI re-ran the suite on the head across 16 shards; nothing rests on the local run.
  • Deviation: primary checkout left detached; worktrees removed. Container hygiene; no effect on the head.
  • Out-of-scope finding: page-header.mdx Layout section still lists "the follow star" unconditionally. Acceptable at this tier because the Props table two headings above now states the host-toggle condition; commandment Add automated testing infrastructure and CI/CD workflows #2 wants the Layout sentence tightened on the next touch of that file (for example "and, where the host wires a favorites toggle, the follow star"). Not required here.
  • Out-of-scope finding: the bump seat deletes the exemption. Agreed; the suite names it. Two more things ride that bump, not this card: the bump seat appends ['page:header', 'showStar'] to the HARVESTED pin in the harvested tombstoned keys are recognised, not exempted — and not published either (the suite's own pattern for every retirement), and objectstack's sdui.manifest.json, which today lists showStar as a page:header input, regenerates on the .objectui-sha hop.

Flags of this review:

  • Sibling pending changeset went false. .changeset/12427-record-header-star.md (unreleased, same next batch) still says "an authored showStar: false still hides it there". Both notes will print in the same release's CHANGELOG. This is the WENT FALSE shape check-changeset-claims.mjs describes; that gate is report-only and keys on file names, which 12427's body does not carry, so it did not fire. 12627's body already states the superseded behaviour ("Before, showStar: false hid the star even where the host wired a toggle"), so a reader can reconcile them. Recommended, not required: one sentence in 12627's changeset in the 11608 shape ("objectui#12427's note that an authored showStar: false still hides the star is superseded by this entry"), or strike that clause from 12427's body — check-changeset-overwrite.mjs reports rather than refuses an edit to a pre-existing changeset, and the hazard it guards is a lost declaration, which a one-clause edit is not.
  • Test name count. the twelve rc.6-obsoleted off-spec exemptions are gone, and their keys are contract now now asserts eleven rows; "twelve" remains the historical count of entries deleted at rc.6, and the inline comment names the row that left and why. Polish under the 完善设计器的每一个细节 #9 rule on counts in names; not required here.
  • Ruling item 3 (Console Pin Gate). That precondition belonged to the objectstack landing and was measured there. objectstack's page-header-show-star-retirement.test.ts walks only objectstack's own tree, so this diff adds no cross-repo coupling at the next pin hop beyond the manifest regeneration above.

Nothing is escalated.

Implemented-by: claude/issue-12627-page-header-show-star
Reviewed-by: session_01SJn1GEkrbbBQkhGC26wEDw

VERDICT: PASS


Generated by Claude Code

@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

Landing · head 485513c · 2026-10-16T09:40Z

  • Checks on 485513c: 33 success, plus 3 expected skips (dependabot, Test (coverage), Test (coverage shard …)). Nothing is red.

  • Mergeable: yes (clean). git merge-tree against current main was clean at the ACCEPT. The queue's merge group runs the full CI on the combined tree.

  • Contract review: CONTRACT_REVIEW_TIER, PASS at this head (6212663417). It is the review owed by the narrowing face: the page:header input and the exported chip prop leave, and nothing is added. Its two optional flags are recorded here and stay as they are:

    • the unreleased sibling changeset 12427-record-header-star.md still describes the old showStar: false behaviour, and this PR's changeset states the superseded behaviour, so a reader can reconcile the two;
    • the "twelve" in a parity test's name is a historical count.

    Neither is a defect, and neither starts a push.

  • Path surface: packages/components (two source files and one test), one console test, two docs pages, one changeset. No governed path.

  • Nothing has been posted since the ACCEPT except the seat's own records, the bundle report and the contract review: no review, no review comment and no objection.

  • Action: mark it ready for review, then enable auto-merge through the merge queue. Fixes #12627 closes the card on merge.


Generated by Claude Code

@objectstack-fleet
objectstack-fleet Bot marked this pull request as ready for review October 16, 2026 09:41
@objectstack-fleet
objectstack-fleet Bot enabled auto-merge October 16, 2026 09:41
@objectstack-fleet
objectstack-fleet Bot added this pull request to the merge queue Oct 16, 2026
Merged via the queue into main with commit 608033b Oct 16, 2026
37 checks passed
@objectstack-fleet
objectstack-fleet Bot deleted the claude/issue-12627-page-header-show-star branch October 16, 2026 09:53
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

apps documentation Improvements or additions to documentation package: components tests

Projects

None yet

2 participants