Repository navigation
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 |
…e parser tier answers (objectui#10981) (objectstack-ai#11006) Fixes objectstack-ai#10981 Clause-②: no — message, `.describe()` and docblock text only; every accept or refuse verdict stays byte-identical. Implemented by the `os-dev` agent dispatched from the `domain:spec @ objectui` seat, session `https://claude.ai/code/session_012UwY3ahMixEFkfTUxMVkYm` (`mode:subagent`). Base `4b742f41d`. PR objectstack-ai#10986 landed on `zod/objectql.zod.ts` meanwhile, so `main` `665025908` was merged in before the final push. Head `ebd156ef5`. ## What changed Only the false clause changes, on four sites. Each clause names the code the parser tier answers for that key and value shape, as measured on the live registry (next section). | site | face | before | after | |---|---|---|---| | `zod/form.zod.ts`, the `FormSchema.mode` refusal (objectui#10286) | zod message and `.describe()`, one string through `retirementTombstone` | "rendered the same form — no error, no warning" | "rendered the same form — no render-time error or warning; only the parser tier's `unknown-prop` warning noticed it" | | `data-display.ts`, the `TimelineSchema.events` docblock (objectui#6170) | TS face, emitted `.d.ts` | "drew an EMPTY rail, with no error and no warning" | "drew an EMPTY rail, with no render-time error or warning; only the parser tier's `unknown-prop` warning noticed it" | | `base.ts`, the `data-table` sentence in the `BaseSchema.bind` docblock | TS face, emitted `.d.ts` | "renders its header over an empty body, with no error and no warning" | "renders its header over an empty body, with no render-time error; nothing on the page says why, but a render-time console warning (`[ObjectUI] DataTable bind:`, objectui#6575) and the parser tier's `unknown-prop` warning both name it" | | `zod/objectql.zod.ts`, the note on `OBJECT_GRID_EXPORT_OPTIONS_GUIDANCE` (objectui#7762) | source note on a non-exported constant; it ships in the emitted JS, in no `.d.ts` | "no error, no warning, no console line" | "no render-time error, warning or console line (only the parser tier's `type-mismatch` warning noticed it)" | - **Why `base.ts` has its own wording.** That site was not silent at render either. `data-table` has logged `[ObjectUI] DataTable bind:` for an authored `bind` since objectui#6575 (`aff3d7aef`, 2026-08-28). The docblock was written a day later (`99a3c2db6`, 2026-08-29). `merge-base --is-ancestor aff3d7a 99a3c2d` answers 0, with the control leg `94d4876df` also answering 0. So "only the parser tier noticed it" would be false there too. - **Why `exportOptions` names `type-mismatch`.** The `object-grid` registration declares `exportOptions` as `type: 'object'`. So `checkType` answers an array, not the undeclared-key branch. - **New pin:** `packages/types/src/__tests__/silence-clause-parser-tier-closure-10981.test.ts`. - **Optional item, taken:** `packages/components/src/renderers/__tests__/header-bar-unknown-prop-parser-tier-10981.test.tsx`, a new file beside `container-declaration-ratchet`. - **Changeset:** `.changeset/10981-silence-clause-parser-tier-closure.md`, `@object-ui/types: patch`. ## The parser tier, measured before each clause was written **Instrument.** The same as PR objectstack-ai#10980: a one-shot probe, deleted and never committed, under `packages/components/src/renderers/__tests__/`. - It imported the components renderers, `fields` and 18 of the 19 `plugin-*` packages (all but `plugin-designer`). `plugin-tree` has no vitest alias, so it came in by relative source path. - The manifest was built from every KNOWN registry key through `manifestFromConfigs`, the way `container-declaration-ratchet.test.tsx` builds it. - Each leg ran `validateTree` on a control and on the control plus the one key, and reports only the diagnostics that key added. - Each leg also rendered through the real `SchemaRenderer`, inside `PredicateScopeProvider` and `SchemaRendererProvider` with a stub data source, all inside `act`. `console.warn` and `console.error` were spied, and the HTML was compared with the control's. | site | keys | value shapes | the parser tier adds | render leg | |---|---|---|---|---| | `FormSchema.mode` | `form`, `ui:form`. Bare `form` resolves to `ui:form`; `view:form` is `skipFallback` | `edit`, `read`, `disabled`, `create`, `view` (the objectui#10286 pin's set) | exactly one `unknown-prop` on `mode`, 10 of 10 legs | 0 warnings, 0 errors on every variant. HTML equals the control's except for one `mode` attribute on the form element | | `TimelineSchema.events` | `timeline` (resolves to `view:timeline`), `view:timeline`, `plugin-timeline:timeline` (the `TimelineRenderer` registration `TimelineSchema` describes) | 2 events; `[]`; `items` plus `events` | exactly one `unknown-prop` on `events`, 7 of 7 | byte-identical HTML, 0 warnings, 0 errors | | `BaseSchema.bind` on `data-table` | `data-table`, `ui:data-table` | `bind: 'users'` and `bind: 'app.settings.users'`, each with `data` absent and with `data: []` | exactly one `unknown-prop` on `bind`, 8 of 8 | byte-identical HTML (the "No results" body in both), 0 errors, and exactly 1 console warning on every variant: `[ObjectUI] DataTable bind: … is ignored` | | `exportOptions` | `object-grid`, `plugin-grid:object-grid` | `['csv', 'xlsx']`, `['csv']`, `[]` | exactly one `type-mismatch` ("expected an object"), 6 of 6 | the control is `{ formats: ['csv', 'json'] }`, the default an array loses to. Byte-identical HTML, the export control and the rows present in both, 0 warnings, 0 errors | **Controls.** - `form` with an invented key draws `unknown-prop`. `view:form` with `mode: 'edit'` draws nothing, because that registration declares `mode`. - On `object-grid`: an `exportOptions` object draws nothing, a string draws `type-mismatch`, and an invented key draws `unknown-prop`. So the probe tells the two codes apart on one node. - `accordion` with a `body` list draws `not-a-container`, the third code. - With `data` absent, the `data-table` control already carries `missing-required-prop` on `data`; the table above counts only what `bind` adds. - The first control render in the file logged one `react-i18next` initialisation warning. No variant did. **The same answer before each retirement (source reading, not executed).** The `mode`, `events` and `exportOptions` sentences are past tense. - `FormSchema.mode`, at `a05c35063^`, the parent of the objectui#10286 commit: the `ui:form` registration declared the same 13 inputs as today, none named `mode`. `plugin-form`'s `form` was `namespace: 'view', skipFallback: true`. `validate.ts` had the same base-prop set, without `mode`, and one `unknown-prop` branch. - `TimelineSchema.events`, at `195052fff^`, the parent of the objectui#6170 tombstone commit: neither `plugin-timeline:timeline` nor `view:timeline` declared `events`. A `git log -G` for an `events` input name over `packages` finds no registration that ever declared one, back to the shallow boundary (2026-07-20). - `exportOptions`, at `f08d1a86a^`, the parent of the objectui#7762 refusal: `GRID_QUERY_INPUTS` declared `exportOptions` as `type: 'object'`. It had done so since `375efb402` (2026-08-17), and objectui#7762 was filed on 2026-09-05. `checkType` gave a single non-enum arm `type-mismatch`, as today. - `BaseSchema.bind` is present tense, measured today. - The history reads ran on a deepened checkout (`git fetch --deepen=4000`, shallow boundary 2026-07-20). ## Census over joined text (the closure nail) **Instrument.** A one-shot script. It enumerates the non-test `.ts` files of `packages/types/src` from the ref with `git ls-tree` and reads each one from the ref. It joins JSDoc and line-comment continuations and `'…' + '…'` concatenations, and unescapes quotes. Then it counts: - A: "no (adjective) error" and "no (adjective) warning" within 60 characters, with no sentence break; - B: the same, in reverse order; - C: "no (adjective) error or / nor / and (adjective) warning", the family's corrected shape; - D: "without (an) error or / and warning"; - E: "neither error nor warning"; - F: "silent…" within 80 characters of a negated warning, in either order; - G, the wide net: any negated warning ("no warning", "without a warning", "never warns", …); - H, the wider net over other nouns: "no diagnostic", "no console line", "without complaint", "not a warning". | reading | base `4b742f41d` | main `665025908` | head `ebd156ef5` | |---|---|---|---| | files enumerated | 67 | 67 | 67 | | A | 4 | 4 | 0 | | B, D, E | 0 | 0 | 0 | | C, and how many are followed by "the parser tier's" | 302, 300 | 302, 300 | 302, 302 | | F | 1 | 1 | 0 | | G | 6 | 6 | 2 | | H | 25 | 25 | 24 | | control: the objectui#10928 clause | 282 | 282 | 282 | | control: the objectui#10959 tail | 18 | 18 | 20 | - **Positive control.** C fires on every one of the 300 known objectui#10928 / objectui#10959 control strings. A fires on exactly the four sites the card names, which were found independently. - **Every non-control hit at base, read.** - A is the four sites and nothing else. The two C hits without the parser tier's clause are two of the four (`base.ts`, `data-display.ts`). F is the fourth site again. - G adds two hits that say "no warning window" (`objectql.ts`, `zod/objectql.zod.ts`, objectui#6475). That is a deprecation window, not a silence claim, so they stay. - H is outside the card's phrasing family. It is listed under Acceptance notes and not changed. ## Every other byte, and only comment and string lines - Substitute the old clause back for the new one on joined text: each head file equals its base file, 4 of 4, against `4b742f41d` and again against `665025908`. - The first four ablation legs put the old clause back with the anchor tool. Each mutated blob equals the base blob byte for byte: `eba1c495f`, `4dfce4ac6`, `b1abfe909` and `e2c561734` are the base blobs of the four files. - `git diff -U0` over the four files: every changed line is a ` * ` JSDoc line or a `+ '…'` string-literal line. - The objectui#10286, objectui#6170, objectui#7762 and `bind` pins pass unchanged; they are in the full `types` run. - **Emitted `dist`**, after `pnpm --filter @object-ui/types build` at head: - the old clauses, both spellings: 0 files; - the `mode` clause: `zod/form.zod.js`, `zod/index.zod.js`; - the `events` clause: `data-display.d.ts`; the `bind` clause: `base.d.ts`; - the `exportOptions` note: `zod/objectql.zod.js`, `zod/index.zod.js` (the emitted JS keeps comments). ## 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 equals HEAD and `git diff HEAD` is empty. - The driver re-proved each restore independently, and ran inside an EXIT / INT / TERM trap. - The types pin imports `../zod/*` source and reads the files from disk. The components pin resolves the registry from source through the vitest aliases. So no build sits between a mutation and a run. | leg | red | red tests | |---|---|---| | the old clause back into `FormSchema.mode` | 3 / 9 | the `mode` arm, the spelling walk, the pairs walk | | the old clause back into `TimelineSchema.events` | 3 / 9 | the `events` docblock, the pairs walk, the parser-tier walk | | the old clause back into `BaseSchema.bind` | 3 / 9 | the `bind` docblock, both walks | | the old clause back into the `exportOptions` note | 2 / 9 | the note, the pairs walk | | the note names `unknown-prop` in place of `type-mismatch` | 1 / 9 | the note | | `zod/ai.zod.ts`, which the pin does not name: an objectui#10928 clause loses its parser-tier half | 1 / 9 | the parser-tier walk | | `header-bar.tsx` starts declaring `title` (components pin) | 4 / 6 | both population legs, both lit controls | - Every leg restored to its HEAD blob (`3a595a747`, `33e3a4770`, `a12a28cf1`, `4e75a80cf` twice, `a40e67ff6`, `ce3850854`) with an empty `git diff HEAD`. After the run, `git status --porcelain` was empty. - **The first `header-bar` attempt was a no-op.** Its replacement contained the anchor, so the tool refused (anchor count 1 to 1) and ran no test. It was re-run with a replacement that does not contain the anchor. The table shows the second run. ## The pins **`silence-clause-parser-tier-closure-10981.test.ts`.** It follows the house style of PR objectstack-ai#10956 and PR objectstack-ai#10980. `@object-ui/types` imports no workspace package, so it holds the prose. - **Zod face.** `FormSchema.mode` is read through its refusal: code `invalid_type` and path `['mode']` first, then the clause. The walk covers every spelling of the objectui#10286 pin, and the `.describe()` text. - **`exportOptions`.** The bare array is refused with `invalid_type` at `['exportOptions']`, with exactly the `.describe()` string. Then the note above `OBJECT_GRID_EXPORT_OPTIONS_GUIDANCE` must carry the clause and name no `unknown-prop`. - **TS face.** The `TimelineSchema.events` and `BaseSchema.bind` docblocks. - **The closure walk.** It reads every non-test `.ts` file of `packages/types/src` from disk, with the root taken from the pin's own `import.meta.url`. - No joined text may pair "no error" with "no warning" (patterns A, B, D, E). - Every C phrasing must have "the parser tier's" within 80 characters after it. - Non-vacuity, by name: the four site files are reached, and both earlier waves' clauses are found. **`header-bar-unknown-prop-parser-tier-10981.test.tsx`.** It answers the open question from PR objectstack-ai#10956 and PR objectstack-ai#10980, on the live components registry. - On `header-bar` and `ui:header-bar`, each of the 9 refused keys draws exactly one `unknown-prop` naming the key. This holds in every value shape the objectui#10387 and objectui#10286 pins refuse. - The control draws nothing. - The lit control shows `crumbs` declared, and no refused key declared. ## Dispatch assumptions, checked 1. **Holds.** There are exactly four sites, one per file, on `4b742f41d` and on `665025908`. The census was widened to patterns A–H above, with controls. 2. **Holds, and made more exact.** - `form` with `mode` draws `unknown-prop`: for all five spellings, on `form` and `ui:form`. - A bare `timeline` with `events` draws `unknown-prop`. The bare key resolves to `view:timeline`. The docblock describes `TimelineRenderer`, which is registered as `plugin-timeline:timeline` (`skipFallback`). That registration also answers `unknown-prop`, so the clause is true for the node the docblock names and for the bare key. - `data-table` with `bind` draws `unknown-prop`. But "only the parser tier noticed it" would be false there, because a render-time console warning fires too (objectui#6575). The site names both. - `object-grid` with an `exportOptions` array draws `type-mismatch`: for three array shapes, on both keys. 3. **Holds**, by source reading at the parent of each retirement. See above. 4. **Changed during the run.** PR objectstack-ai#10986 landed (`8aa68b159`) on `zod/objectql.zod.ts`. `main` `665025908` was merged in before the final push, with no conflict. The note edited here is away from that hunk. PR objectstack-ai#10997 had not landed at `665025908`. ## Gates, head `ebd156ef5` All ran after the merge commit. Exit codes were captured before any pipe. - `pnpm --filter @object-ui/types build` → 0. Its `check-dist-completeness` verified 134 emitted files. - `pnpm --filter @object-ui/types type-check` → 0. `tsc -p tsconfig.test.json --listFiles` includes the new pin. - `pnpm --filter @object-ui/types lint` → 0, with 0 errors. The 295 warnings are existing `no-explicit-any` ones; none is in the new file. - `pnpm exec vitest run packages/types/` → 0: 272 files and 5993 tests passed. - Outside `types` → 0: 27 files and 931 tests passed. - The script tests that read `packages/types/src`: `body-dialect-producer-scan`, `changeset-polarity-census`, `check-action-forward-parity`, `check-changeset-claims`, `check-component-surface-parity`, `check-doc-component-types`, `check-doc-example-types`, `check-handler-key-read-sites`, `check-readme-exports`, `check-spec-symbol-derivation`, `component-node-vocabulary-7434`, `one-authority-per-exported-name-6273`, `check-pending-changeset-literals`, `spec-symbol-ledger-types-7265`, `unconsumed-widget-option-claim-6186`, `vite-types-zod-lazy`; - `component-fixture-declared-keys` in `examples/schema-catalog`; - the new components pin, `container-declaration-ratchet`, the four `header-bar` component tests, `skill-guide-data-table-binding` and `data-table-bind-diagnostic`; - the parser pins `body-dialect-6771` and `containment-declared-slot-9910`. - `pnpm --filter '@object-ui/components^...' build`, then `pnpm --filter @object-ui/components type-check` → 0. `tsconfig.test.json --listFiles` includes the new components pin. `eslint` over the two new test files → 0, with no findings. - `check-changeset-presence`, `check-changeset-no-major`, `check-changeset-fixed`, `check-changeset-overwrite` → 0. `check-changeset-claims` → 0; it is report-only. - `pnpm check:control-bytes`, `check:new-line-citations` (0 new), `check:pending-changeset-literals`, `check:test-path-roots`, `check:phantom-deps` and `check:self-import` → 0. - `check-governed-queue-guard --test` over the 7 paths → NOT GOVERNED. - Declared to CI: repo-wide `pnpm lint`, full `pnpm test` and the other workflow gates. ## Acceptance notes Not changed here, and left for the seat to route. - **Same false claim, outside this package.** `skills/objectui/rules/protocol.md`, the "Readers only." paragraph, says a `bind` on `data-table` renders its header over an empty body "no error, no warning". The render leg and the parser leg above both contradict it. It is on the governed `skills/**` surface, outside this card. - **Same claim in unpublished test prose.** The headers of `base-bind-declared.test.ts` and `object-grid-export-options-refusal-7762.test.ts` repeat it. `mirror-partial-record-narrowing-8516.test.ts` has a different "no error and no warning" claim, about grid columns. All three are test files, outside the census. - **Pending changesets.** `.changeset/7762-object-grid-export-options-bare-array-refusal.md` and `.changeset/6575-data-table-bind-diagnostic.md` describe the pre-fix behaviour in the old words. Pending changesets are out of scope here. - **Adjacent wording, left in place.** - The `base.ts` heading "the one documented silent failure" stays. The corrected sentence now says in which sense it is silent: nothing on the page. - The `exportOptions` guidance string says an array "is silently dropped for the csv/json default". That is present tense about the renderer, and "silently" alone is outside the phrasing family. - **H, the "no diagnostic" nouns (24 at head).** Most are scoped to a named tier or instrument: "on either face" (`objectql.ts`), "zero unresolved-module diagnostics" from `tsc`, `checkType` by name, the TS index signature. A few are unscoped claims about an authored value: `ai.ts` (`maxResults`), `crud.ts`, `data-display.ts` (three) and `zod/data-display.zod.ts`. They were not measured here. - **Observation.** A `mode` on a `form` reaches the DOM as an inert `mode` attribute on the form element. The visible form is identical. - **Boundary.** `view:form` declares `mode` (enum `create`, `edit`, `view`). It is a different registration and node type, which the `FormSchema` docblock does not describe. - **A parser-tier finding, reported to the seat.** `validateTree` answers `bind` with `unknown-prop` on `list` and `tree-view` too, although both read `bind` through `useDataScope`. No registration declares a `bind` input, and the parser's base-prop set has no `bind`. --- _Generated by [Claude Code](https://claude.ai/code/session_012UwY3ahMixEFkfTUxMVkYm)_ --------- Co-authored-by: Claude <noreply@anthropic.com>
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