fix(types): retire the header-bar keys nothing reads or authors (nav, left, center, height) (objectui#10387) - #10395
Conversation
… left, center, height) ADR-0049 enforce-or-remove under the objectui#7759 ruling (rule 2, D1-(ii)): the key is objectui-own, the spec is silent, and the read site is the truth. A runtime probe through the real SchemaRenderer drew the header identical to its absence for every value; no in-tree document authors any of the four. Both faces now carry the tombstone (?: never beside retirementTombstone). title, logo, right and sticky are also unread but have in-tree authors and are left for the seat to decide. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01877XiBYSaRCk2CU7cMSg3S
|
changeset-claim-re-read
|
…ader-bar-unread-keys
✅ Console Performance Budget
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
Size Limits
|
…igrate their authors PM decision A on the open question: the four keys have no read site (runtime probe) and the spec is silent, so they retire like nav/left/center/height. Their only authors were docs and a type-check example; those now use crumbs and actions. The two components tests drop their inert title filler. Retiring logo empties the HeaderBarSchema WIDER entry and its WIDER_ARMS row; the header figures are re-derived (7 / 10 / 10, split 5 / 5 / 0 / 0). The ledger's arm-enumeration non-vacuity check now reads a fixed union control slot (SidebarSchema.content), because the ledger no longer holds a union. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01877XiBYSaRCk2CU7cMSg3S
✅ Console Performance Budget
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
Size Limits
|
…-unread-keys Resolves the WIDER ledger header: objectui#10334 (via #10338) retired the DashboardComponentSchema::dateRange row, and this branch retires the HeaderBarSchema::logo entry. Re-derived figures: 7 / 9 / 9, split 5 / 4 / 0 / 0, with both history sentences kept in order. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01877XiBYSaRCk2CU7cMSg3S
✅ Console Performance Budget
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
Size Limits
|
Contract reviewServed-tier: ① Contract correctness.
② Tests.
③ Blast radius. On a fresh worktree at head:
Out of scope, not blocking:
Implemented-by: |
Fixes #10387
Clause-②: yes
Retires all eight
HeaderBarSchemakeys theheader-barrenderer never reads (title,logo,nav,left,center,right,sticky,height) from both faces. It uses the ADR-0049 tombstone shape objectui#10286 used forvariant:?: neveron the TS face beside aretirementTombstone(...)refusal in the zod mirror. It also migrates the only in-tree authors (docs and a type-check example) tocrumbs/actions.Authority: objectui#7759 ruling 5617465269 rule 2 (objectui-own key, so the read site is the truth), D1-(ii) (both faces dead and the spec silent, so retire), and ADR-0049 enforce-or-remove. The PM seat ruled decision A on the four keys that had authors (
title,logo,right,sticky): retire them in this PR and migrate the authors.1. The read set, measured at runtime (not by grep)
A one-off probe (deleted afterwards, not committed) rendered
{ type: 'header-bar', crumbs: [{ label: 'Home' }] }through the realSchemaRendererand the real registry insideSidebarProvider. It varied one key at a time and comparedinnerHTMLwith the render that omitted the key:The renderer's one function takes only
{ schema }and readscrumbs,search,actionsandrightContent. No spread props reach it.Spec:
packages/spec/srcat objectstack9d81af71and the installed 17.4.0disthave zeroheader-bar/HeaderBarhits. The control wordbreadcrumbhits in both.2. Authors, and how they migrated
titlepackages/types/README.md(Composable example),content/docs/guide/objectos-integration.mdx(pageheader),packages/types/examples/dashboard.ts; inerttitle: 'H'filler inheader-bar-right-content-numeric-falsy.test.tsx(3 sites) andnode-slot-numeric-falsy.test.tsx(1 site)crumbs: [{ label: 'My App' }]; dashboard:crumbs: [{ label: 'Object UI Dashboard' }]; tests: filler dropped (it never rendered, so each test'sCHROMEbaseline is unchanged)logopackages/types/examples/dashboard.ts('/logo.svg')rightpackages/types/examples/dashboard.ts(Profile button)actionsstickypackages/types/examples/dashboard.ts(true)nav,left,center,heightThe guide's header also carried an undeclared
navigationbag that nothing reads (the page'ssidebaralready holds the same items). It was dropped together withtitle, because the node was rewritten anyway.The
header-barregistrationinputsoffer onlycrumbs,search,actionsandrightContent, so the designer never offered any of the eight.3. Ledger (
zod-mirror-parity.test.ts)navigation.zod.ts#HeaderBarSchemaWiderThanDeclaredentry (logo) and itsWIDER_ARMSrow (['CONCRETE', 'CONCRETE']) are removed. A note records where the entry stood.logowas the last one, so the pin went red on a shrinking ledger even though the unwrapper worked. Its union direction now also measures a fixed control slot outside the ledger,SidebarSchema.content(single-or-list, two arms). The single-arm direction still reads the ledger's own rows. After the merge,WIDER_ARMSholds zero multi-arm rows, so that control slot is now the only two-arm reading the pin gets. It passes.00cdaff1f(merge2ea13bc2a), thence6bd99a5, which is PR fix(types): dashboard dateRange takes the spec authoring member on both faces (objectui#10334) #10338 / objectui#10334 (mergea74282b89). The second merge conflicted only on the WIDER header paragraph. It was resolved by re-deriving the figures and keeping both history sentences in order. The merge changed nothing on this branch beyond the ledger figures:navigation.ts,navigation.zod.tsand the pin test are byte-identical to968cd7698.4. Pins and reverse verification
packages/types/src/__tests__/header-bar-unread-keys-10387.test.tshas 19 tests. They cover:logoas a URL string, a node and a node list);codeand message head, naming what the renderer reads instead;@ts-expect-errorper key, checked bytsc -p tsconfig.test.json.Reverse verification ran from the committed state via objectstack
scripts/ablation-replace.mjs: the anchor must hit, the blob must move, the file is restored to the HEAD blob, andgit diff HEADmust be empty.095636b79)z.array(NavLinkSchema)arm restored095636b79)968cd7698)968cd7698)z.string()arm restoredIn every leg the lit control stayed green. The restore is proven by the blob matching HEAD (
385141979aacon968cd7698) and an emptygit diff HEAD.5. Verification (head
a74282b89; ablation and shape gate as noted)pnpm --filter '@object-ui/components^...' build, thenpnpm --filter @object-ui/types type-check(src, examples and test projects) andpnpm --filter @object-ui/components type-check: exit 0.vitest run packages/types/ examples/schema-catalog/plus the three header-bar renderer tests: 265 files / 7437 tests passed ona74282b89.968cd7698, NOT re-run ona74282b89: that merge brought in main's objectui#10334 type change, so the shape-gate reading below is for the pre-merge tree; CI runs it on the merge):@objectstack/specfrom objectstackorigin/main9d81af714f49in a throwaway worktree and packed it;node scripts/spec-main-shape-gate.mjs inject --tarball ... --sha 9d81af714f49... --upstream-checkout ...: exit 0;TURBO_FORCE=true turbo run type-check --filter=@object-ui/types --filter=@object-ui/components: 10/10 tasks;report --status 0: "objectui type-checks against@objectstack/specat that commit".check:component-surface-parity,check:designer-field-key-parity,check:prompt-keys,check:doc-types,check:doc-fences,check:new-line-citations,check:control-bytes,check:changeset-claims,check:pending-changeset-literals,check:spec-symbols(on the normal install),check:doc-example-readers,check:test-path-roots,check-changeset-presence,check-changeset-no-major.check:doc-snippetsandcheck:doc-examples. Reason: PRECONDITION NOT MET (exit 2); they need a 34-package build, so they are left to CI..ts/.tsxfiles (--no-inline-config --format json): 7 files, 0 errors, 6 warnings. All six areno-explicit-anyon lines this PR did not edit. The population isfiles: ['**/*.{ts,tsx}']ineslint.config.js. Type-aware linting is off, so this diff cannot change the lint result of any file it does not touch.Acceptance notes (not filed)
classNameis also unread byheader-bar(see the probe row above). The PM seat is filing it.NavLinkSchema/NavLinklose theirheader-barconsumer.SidebarSchema.navstill uses them.header-bar.mdxlists onlycrumbsand the base keys. Its usage note says the height is a fixedh-16, but the renderer usesh-14 sm:h-16. Neither is touched here.check:spec-symbolsexits 1 while spec main is injected into the store. Spec main now exports names (for exampleObjectTimelinePropsandObjectTreeProps) that plugin packages already declare locally. This comes from the spec bump, not from this diff: it is green on the normal install.Changeset
.changeset/10387-header-bar-unread-keys-retired.md:minoron@object-ui/types. The body has the breaking notes and the migration for all eight keys.Implemented by the os-dev agent dispatched from PM seat
session_01877XiBYSaRCk2CU7cMSg3S(domain:spec#1).Generated by Claude Code