fix(types): header-bar refusals and nine body docblocks name the parser tier's unknown-prop warning (objectui#10959) - #10980
Conversation
…er tier's unknown-prop warning The nine HeaderBarSchema refusal strings (title, logo, nav, left, center, right, sticky, height, variant) and the nine `body?: never` docblocks in layout.ts (box, span, container, flex, stack, grid, scroll-area) and form.ts (toggle, form) said an authored value drew "no error, no warning". The render path is as described, but the parser tier is not: validateTree answers each of those keys, on the bare and the ui: registration, with an `unknown-prop` warning. Only that clause changes; every other byte of each string and docblock is kept. Co-authored-by: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012UwY3ahMixEFkfTUxMVkYm
…ody docblocks; changeset The pin reads one header-bar key of each clause form through its refusal (invalid_type at the key's own path, then the clause substring), every header-bar member of the objectui#10387 / objectui#10286 retirements, the body docblock of BoxSchema and FormSchema, and every objectui#8284 body docblock in layout.ts and form.ts. Changeset: @object-ui/types patch. Co-authored-by: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012UwY3ahMixEFkfTUxMVkYm
|
changeset-claim-re-read
|
✅ 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: PR #10980 for card objectui#10959. Read-only inputs: the card body and its three comments (triage Check-runs on ① Derived judgmentsFive files:
Nothing judged wrong. ② Semver level
③ Boundary flags
Implemented-by: VERDICT: PASS |
Fixes #10959
Clause-②: no — message,
.describe()and docblock text only; every accept or refuse verdict stays byte-identical.Implemented by the
os-devagent dispatched from thedomain:spec @ objectuiseat, sessionhttps://claude.ai/code/session_012UwY3ahMixEFkfTUxMVkYm(mode:subagent). Base1345e182d, head7089f691c.What changed
Only the false clause changes. It changes on 18 sites of two kinds. The objectui#10928 wording names
not-a-container, which would be false here, so it is not reused.HeaderBarSchemarefusals:title,logo,nav,left,center,right,sticky,height(objectui#10387) andvariant(objectui#10286). Each message is also its.describe()text, throughretirementTombstone.variant, "no class").unknown-propwarning noticed it".variantkeeps "no class" in place of "no element".body?: neverdocblocks (TS face, emitted.d.ts). There are 9:box,span,container,flex,stack,grid,scroll-areainlayout.ts, andtoggle,forminform.ts(objectui#8284).unknown-propwarning noticed it".packages/types/src/__tests__/unknown-prop-parser-tier-clause-10959.test.ts..changeset/10959-unknown-prop-parser-tier-clause.md,@object-ui/types: patch.The parser tier, measured before the clause was written
Instrument. A one-shot probe, deleted and not committed. It sat under
packages/components/src/renderers/__tests__/and built the manifest from the live registry the waycontainer-declaration-ratchet.test.tsxdoes: every KNOWN key, throughmanifestFromConfigs. It importedcomponents,fieldsand 18 of the 19plugin-*packages (all butplugin-designer). Then it ranvalidateTreeonce per leg. It also rendered each leg through the realSchemaRenderer, spying onconsole.warnandconsole.error, and compared the HTML with the leg's control.Population and result.
header-barandui:header-bar(inputscrumbs,search,actions,rightContent) × the 9 keys × every value the objectui#10387 / objectui#10286 pins use (strings, a node, a node list, booleans, numbers, the 4variantspellings)unknown-propwarning; HTML byte-identical to the control; 0 console warnings, 0 console errorsui:key of the 9bodynodes (18 keys, each declares thechildreninput and nobodyinput) ×bodyas a list, a single node and a scalarunknown-propwarning (thecheckRetiredBodyDialectsentence that nameschildren); HTML byte-identical to the control; 0 console warnings, 0 console errorsAnswer to the mechanism assumption about value shape. Scalar and list give the same code on these nine.
checkRetiredBodyDialectanswersnot-a-containeronly where the registration declares nochildreninput, and all 18 keys declare it. So the list, the single node and the scalar all drawunknown-prop.Controls.
accordionandinputdeclare nochildreninput. There abodylist drawsnot-a-container, a scalarbodydrawsunknown-prop, and an invented key drawsunknown-prop. So the probe can tell the two codes apart.header-barcontrol renders aheaderelement with 0 console warnings and 0 console errors.header-barbare. It logged theuseSidebarprovider error on the control and on every leg alike, so its render comparison proved nothing.sidebar-provider, the context the containment ratchet uses for the sidebar parts.The same answer before each retirement (source reading, not executed). The strings and docblocks are in the past tense, so the pre-retirement tree was read too.
236a71fe3, the parent of the objectui#8284 tombstone commitb1777aef3:validate.tshad nobodyin its base-prop set and nocheckRetiredBodyDialect, so an undeclared key drewunknown-prop;bodyinput (zero quoted'body'/"body"in the nine files).header-bar.tsxdid not change between6214db63f(2026-09-11) and the two retirements (objectui#10286a05c35063, objectui#103879b281519f). Read ata05c35063, its registration declared the same four inputs it declares today.Census, base
1345e182dvs head7089f691cThese counts are over joined text: JSDoc continuations and
'…' + '…'joins are removed, and an escaped quote is unescaped.header-barrefusal headzod/navigation.zod.tslayout.tsform.ts.tsfiles ofpackages/types/srcat base (enumerated from the ref withgit ls-tree, not from the working tree), the old string clause and the old docblock clause occur only in these three files.dist, afterpnpm --filter @object-ui/types buildat head:zod/navigation.zod.jsandzod/index.zod.js, 9 each);layout.d.ts7,form.d.ts2).safeValidateSchemaonheader-baranswers as follows:title:invalid_typeat pathtitle, and the message carries the new clause and not the old one;variant: the same;crumbs): success.Every other byte, and only string and comment lines
git diff -U0over the three files: every changed line is a+ '…'string-literal line (zod) or a*JSDoc continuation line. No other line changed.Reverse verification (ablation), after the fix was committed
Instrument. objectstack's
scripts/ablation-replace.mjs, in WRAP mode, run from this worktree. The anchor must hit exactly once, and the on-disk blob must move. The tool proves each restore (blob == HEAD,git diff HEADempty), and the driver re-proves it independently. The types tests import../zod/*source and readlayout.ts/form.tsfrom disk, so no build sits between a mutation and the run.variant's string59f587b96variantarm, theheader-barpopulationtitle's stringc80665c61titlearm, theheader-barpopulationBoxSchema.bodydocblock2383fde4fBoxSchemadocblock, the docblock populationGridSchema.bodydocblock (not named by the pin)a3ac19fa8ToggleSchema.bodydocblock inform.ts(not named by the pin)5e4c2ac67Each leg restored to its HEAD blob (
ad46ba82c,a90b246c7,daad6d395) with an emptygit diff HEAD. After the run,git status --porcelainwas empty.The pin
It follows the house style of PR objectui#10956's pin.
@object-ui/typesdeclares no workspace dependency, so the pin holds the prose, not the parser.titleandvariant, one per clause form, it asserts codeinvalid_typeand path[key]first, then the clause substring. It also asserts that neither the old clause nornot-a-containerappears.HeaderBarSchemamember whose refusal is an objectui#10387 / objectui#10286 retirement carries the clause. Non-vacuity is by name (title,variant).layout-default-jsdoc-7361.test.ts.bodydocblocks ofBoxSchemaandFormSchemacarry the clause.layout.tsandform.tsthat carries objectui#8284's sentence carries it too. Non-vacuity: both files are reached.import.meta.url, never the cwd (check:test-path-rootspasses).bodyhalf is pinned inpackages/sdui-parser, by "the retiredbodyspelling follows the SAME predicate" (containment-declared-slot-9910.test.ts) and "abodychild list under a CONTAINER drawsunknown-propnamingchildren" (body-dialect-6771.test.ts). Theheader-barhalf isvalidateTree's generic undeclared-key branch, and no pin there namesheader-bar. See Open question.Dispatch assumptions, checked
1345e182d, a descendant of328abeb55(merge-base --is-ancestorexit 0), with controls. See Census.unknown-prop. None drawsnot-a-container, because all 18bodykeys declarechildren. See the table.content-channel-parser-tier-clause-10928.test.ts) does not name the 8HeaderBarSchemasites. Its population walk reads only the family-Dbody/childrenmembers (reads NEITHER content channel:). It passes unchanged at head, so it is not edited. The 8 sites appear only in PR objectui#10956's description.Gates, head
7089f691cAll ran after the last commit. Exit codes were captured before any pipe.
pnpm --filter @object-ui/types build→ 0. It includescheck-dist-completeness: 134 emitted files verified.pnpm --filter @object-ui/types type-check→ 0.tsc -p tsconfig.test.json --listFilesincludes the new pin.pnpm --filter @object-ui/types lint→ 0, with 0 errors. The new file has no warnings; the package has 295 existingno-explicit-anywarnings.pnpm exec vitest run packages/types/→ 0: 269 files and 5962 tests passed.typesthat read the edited files, plus the parser pins named above → 0: 9 files, 276 tests.scripts/__tests__/check-doc-component-types.test.ts,check-spec-symbol-derivation.test.ts,one-authority-per-exported-name-6273.test.tsandcheck-pending-changeset-literals.test.ts;header-barcomponent tests;body-dialect-6771andcontainment-declared-slot-9910.check-changeset-presence,check-changeset-no-major,check-changeset-fixedandcheck-changeset-overwrite→ 0.check-changeset-claims→ 0. It is report-only. It lists 17 pending changesets that name an edited file. None of them quotes either clause this PR changes. The only pending changeset carrying the old string clause is objectui#10928's, about the family-D refusals, and that is still true.pnpm check:control-bytes,check:new-line-citations(0 new),check:pending-changeset-literals,check:test-path-rootsandcheck:phantom-deps→ 0.check-governed-queue-guard --testover the 5 paths → NOT GOVERNED.pnpm lint, fullpnpm testand the other workflow gates.Acceptance notes
Same family, not changed here, and left for the seat to route. Each carries the old silence claim, and the parser tier answers it (live registry, same probe):
zod/form.zod.ts, theFormSchema.moderefusal (objectui#10286): "every spelling rendered the same form — no error, no warning".formwithmodedrawsunknown-prop.data-display.ts, theTimelineSchema.eventsdocblock (objectui#6170): "drew an EMPTY rail, with no error and no warning". A baretimelinewitheventsdrawsunknown-prop. The live registry resolves that key toplugin-timeline'sviewregistration, so this reading is about that registration. This file is PR objectui#10972's surface.base.ts, thebinddocblock: "data-table… renders its header over an empty body, with no error and no warning".data-tablewithbinddrawsunknown-prop.zod/objectql.zod.ts, theexportOptionsdescribe text (objectui#7762): "no error, no warning, no console line".object-gridwith anexportOptionsarray drawstype-mismatch.Boundary: the names
gridandformalso exist asview:grid,view:formandfield:grid. Those are different registrations and node types, which theGridSchema/FormSchemadocblocks do not describe. None of them declareschildren, so abodylist there drawsnot-a-container.Open question
Should a live-registry pin in
packages/componentsalso hold the parser behaviour theheader-barclause describes? No such pin exists today. This PR does not add one: it is outside the claimed file surface, and the same question is open from PR objectui#10956.Generated by Claude Code