Skip to content

Commit 42687ba

Browse files
fix(types): header-bar refusals and nine body docblocks name the parser tier's unknown-prop warning (objectui#10959) (#10980)
Fixes #10959 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 `1345e182d`, head `7089f691c`. ## 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. - **Refusal strings (zod face).** These are the 9 `HeaderBarSchema` refusals: `title`, `logo`, `nav`, `left`, `center`, `right`, `sticky`, `height` (objectui#10387) and `variant` (objectui#10286). Each message is also its `.describe()` text, through `retirementTombstone`. - Before: "no error, no warning, no element" (for `variant`, "no class"). - After: "no render-time error or warning and no element; only the parser tier's `unknown-prop` warning noticed it". `variant` keeps "no class" in place of "no element". - **`body?: never` docblocks (TS face, emitted `.d.ts`).** There are 9: `box`, `span`, `container`, `flex`, `stack`, `grid`, `scroll-area` in `layout.ts`, and `toggle`, `form` in `form.ts` (objectui#8284). - Before: "rendered an EMPTY element with no error and no warning". - After: "rendered an EMPTY element with no render-time error or warning; only the parser tier's `unknown-prop` warning noticed it". - **New pin:** `packages/types/src/__tests__/unknown-prop-parser-tier-clause-10959.test.ts`. - **Changeset:** `.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 way `container-declaration-ratchet.test.tsx` does: every KNOWN key, through `manifestFromConfigs`. It imported `components`, `fields` and 18 of the 19 `plugin-*` packages (all but `plugin-designer`). Then it ran `validateTree` once per leg. It also rendered each leg through the real `SchemaRenderer`, spying on `console.warn` and `console.error`, and compared the HTML with the leg's control. **Population and result.** | population | legs | what each leg adds | |---|---|---| | `header-bar` and `ui:header-bar` (inputs `crumbs`, `search`, `actions`, `rightContent`) × the 9 keys × every value the objectui#10387 / objectui#10286 pins use (strings, a node, a node list, booleans, numbers, the 4 `variant` spellings) | 44 | exactly one `unknown-prop` warning; HTML byte-identical to the control; 0 console warnings, 0 console errors | | the bare and `ui:` key of the 9 `body` nodes (18 keys, each declares the `children` input and no `body` input) × `body` as a list, a single node and a scalar | 54 | exactly one `unknown-prop` warning (the `checkRetiredBodyDialect` sentence that names `children`); HTML byte-identical to the control; 0 console warnings, 0 console errors | **Answer to the mechanism assumption about value shape.** Scalar and list give the same code on these nine. `checkRetiredBodyDialect` answers `not-a-container` only where the registration declares no `children` input, and all 18 keys declare it. So the list, the single node and the scalar all draw `unknown-prop`. **Controls.** - `accordion` and `input` declare no `children` input. There a `body` list draws `not-a-container`, a scalar `body` draws `unknown-prop`, and an invented key draws `unknown-prop`. So the probe can tell the two codes apart. - The `header-bar` control renders a `header` element with 0 console warnings and 0 console errors. - A first run rendered `header-bar` bare. It logged the `useSidebar` provider error on the control and on every leg alike, so its render comparison proved nothing. - That run was discarded. The render leg was re-run inside `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. - At `236a71fe3`, the parent of the objectui#8284 tombstone commit `b1777aef3`: - `validate.ts` had no `body` in its base-prop set and no `checkRetiredBodyDialect`, so an undeclared key drew `unknown-prop`; - none of the nine registrations declared a `body` input (zero quoted `'body'` / `"body"` in the nine files). - `header-bar.tsx` did not change between `6214db63f` (2026-09-11) and the two retirements (objectui#10286 `a05c35063`, objectui#10387 `9b281519f`). Read at `a05c35063`, its registration declared the same four inputs it declares today. ## Census, base `1345e182d` vs head `7089f691c` These counts are over joined text: JSDoc continuations and `'…' + '…'` joins are removed, and an escaped quote is unescaped. | file | old string clause | new string clause | old docblock clause | new docblock clause | control: `header-bar` refusal head | control: objectui#8284 docblock sentence | control: objectui#10928 clause | absent token | |---|---|---|---|---|---|---|---|---| | `zod/navigation.zod.ts` | 9 → 0 | 0 → 9 | 0 → 0 | 0 → 0 | 9 / 9 | 0 / 0 | 10 / 10 | 0 / 0 | | `layout.ts` | 0 → 0 | 0 → 0 | 7 → 0 | 0 → 7 | 0 / 0 | 7 / 7 | 12 / 12 | 0 / 0 | | `form.ts` | 0 → 0 | 0 → 0 | 2 → 0 | 0 → 2 | 0 / 0 | 2 / 2 | 28 / 28 | 0 / 0 | - Over all 67 non-test `.ts` files of `packages/types/src` at base (enumerated from the ref with `git ls-tree`, not from the working tree), the old string clause and the old docblock clause occur only in these three files. - **Emitted `dist`**, after `pnpm --filter @object-ui/types build` at head: - old string clause 0, new 18 (`zod/navigation.zod.js` and `zod/index.zod.js`, 9 each); - old docblock clause 0, new 9 (`layout.d.ts` 7, `form.d.ts` 2). - **On the built dist**, `safeValidateSchema` on `header-bar` answers as follows: - with `title`: `invalid_type` at path `title`, and the message carries the new clause and not the old one; - with `variant`: the same; - control (only `crumbs`): success. ## Every other byte, and only string and comment lines - Take each head file and substitute the old clause back for the new one: 9, 7 and 2 substitutions. Each result is byte-identical to the base file. - `git diff -U0` over the three files: every changed line is a `+ '…'` string-literal line (zod) or a ` * ` JSDoc continuation line. No other line changed. - On the docblock face, the replaced text wraps onto three lines where the old text used two. The joined text differs only in the clause. - The objectui#10387 and objectui#10286 pins (codes, paths, message heads) pass unchanged. ## 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 HEAD` empty), and the driver re-proves it independently. The types tests import `../zod/*` source and read `layout.ts` / `form.ts` from disk, so no build sits between a mutation and the run. | leg: the old clause put back into | blob mutated to | red / 7 | red tests | |---|---|---|---| | `variant`'s string | `59f587b96` | 2 | the `variant` arm, the `header-bar` population | | `title`'s string | `c80665c61` | 2 | the `title` arm, the `header-bar` population | | `BoxSchema.body` docblock | `2383fde4f` | 2 | the `BoxSchema` docblock, the docblock population | | `GridSchema.body` docblock (not named by the pin) | `a3ac19fa8` | 1 | the docblock population | | `ToggleSchema.body` docblock in `form.ts` (not named by the pin) | `5e4c2ac67` | 1 | the docblock population | Each leg restored to its HEAD blob (`ad46ba82c`, `a90b246c7`, `daad6d395`) with an empty `git diff HEAD`. After the run, `git status --porcelain` was empty. ## The pin It follows the house style of PR objectui#10956's pin. `@object-ui/types` declares no workspace dependency, so the pin holds the prose, not the parser. - **Zod face.** - For `title` and `variant`, one per clause form, it asserts code `invalid_type` and path `[key]` first, then the clause substring. It also asserts that neither the old clause nor `not-a-container` appears. - Then the population: every `HeaderBarSchema` member whose refusal is an objectui#10387 / objectui#10286 retirement carries the clause. Non-vacuity is by name (`title`, `variant`). - **TS face.** Precedent for pinning docblock text: `layout-default-jsdoc-7361.test.ts`. - The `body` docblocks of `BoxSchema` and `FormSchema` carry the clause. - Then the population: every docblock in `layout.ts` and `form.ts` that carries objectui#8284's sentence carries it too. Non-vacuity: both files are reached. - The repo root comes from the pin's own `import.meta.url`, never the cwd (`check:test-path-roots` passes). - **Where the parser half lives.** The `body` half is pinned in `packages/sdui-parser`, by "the retired `body` spelling follows the SAME predicate" (`containment-declared-slot-9910.test.ts`) and "a `body` child list under a CONTAINER draws `unknown-prop` naming `children`" (`body-dialect-6771.test.ts`). The `header-bar` half is `validateTree`'s generic undeclared-key branch, and no pin there names `header-bar`. See Open question. ## Dispatch assumptions, checked 1. **Holds.** Counts are 9 / 7 / 2 on base `1345e182d`, a descendant of `328abeb55` (`merge-base --is-ancestor` exit 0), with controls. See Census. 2. **Holds, and made more exact.** Every key and every value shape draws `unknown-prop`. None draws `not-a-container`, because all 18 `body` keys declare `children`. See the table. 3. **Does not hold.** The objectui#10928 pin (`content-channel-parser-tier-clause-10928.test.ts`) does not name the 8 `HeaderBarSchema` sites. Its population walk reads only the family-D `body` / `children` members (`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. 4. **Not re-scanned by this dev.** The PM files-API scan is taken as given. This diff touches none of PR objectui#10972's or PR objectui#10977's files. ## Gates, head `7089f691c` All ran after the last commit. Exit codes were captured before any pipe. - `pnpm --filter @object-ui/types build` → 0. It includes `check-dist-completeness`: 134 emitted files verified. - `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 new file has no warnings; the package has 295 existing `no-explicit-any` warnings. - `pnpm exec vitest run packages/types/` → 0: 269 files and 5962 tests passed. - The tests outside `types` that 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.ts` and `check-pending-changeset-literals.test.ts`; - the three `header-bar` component tests; - `body-dialect-6771` and `containment-declared-slot-9910`. - `check-changeset-presence`, `check-changeset-no-major`, `check-changeset-fixed` and `check-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-roots` and `check:phantom-deps` → 0. - `check-governed-queue-guard --test` over the 5 paths → NOT GOVERNED. - Declared to CI: repo-wide `pnpm lint`, full `pnpm test` and 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`, the `FormSchema.mode` refusal (objectui#10286): "every spelling rendered the same form — no error, no warning". `form` with `mode` draws `unknown-prop`. - `data-display.ts`, the `TimelineSchema.events` docblock (objectui#6170): "drew an EMPTY rail, with no error and no warning". A bare `timeline` with `events` draws `unknown-prop`. The live registry resolves that key to `plugin-timeline`'s `view` registration, so this reading is about that registration. This file is PR objectui#10972's surface. - `base.ts`, the `bind` docblock: "`data-table` … renders its header over an empty body, with no error and no warning". `data-table` with `bind` draws `unknown-prop`. - `zod/objectql.zod.ts`, the `exportOptions` describe text (objectui#7762): "no error, no warning, no console line". `object-grid` with an `exportOptions` array draws `type-mismatch`. Boundary: the names `grid` and `form` also exist as `view:grid`, `view:form` and `field:grid`. Those are different registrations and node types, which the `GridSchema` / `FormSchema` docblocks do not describe. None of them declares `children`, so a `body` list there draws `not-a-container`. ## Open question Should a live-registry pin in `packages/components` also hold the parser behaviour the `header-bar` clause 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](https://claude.ai/code/session_012UwY3ahMixEFkfTUxMVkYm)_ --------- Co-authored-by: Claude <noreply@anthropic.com>
1 parent deca847 commit 42687ba

5 files changed

Lines changed: 236 additions & 27 deletions

File tree

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
---
2+
'@object-ui/types': patch
3+
---
4+
5+
Correct a false clause in the `header-bar` refusal messages and in nine `body?: never` docblocks (objectui#10959).
6+
7+
The `HeaderBarSchema` refusals for `title`, `logo`, `nav`, `left`, `center`, `right`, `sticky`, `height` (objectui#10387) and `variant` (objectui#10286) said an authored value drew "no error, no warning". So did the `body?: never` docblocks on `box`, `span`, `container`, `flex`, `stack`, `grid`, `scroll-area`, `toggle` and `form` (objectui#8284), which ship in the emitted `.d.ts`. The render path is as described, but the parser tier is not: `validateTree` answers each of those keys with an `unknown-prop` warning. So the refusals now say "no render-time error or warning and no element; only the parser tier's `unknown-prop` warning noticed it" (`variant` keeps "no class" where the others say "no element"), and the docblocks say the `body` "rendered an EMPTY element with no render-time error or warning; only the parser tier's `unknown-prop` warning noticed it".
8+
9+
Message, `.describe()` and documentation text only: every document is accepted or refused exactly as before, with the same issue code at the same path. Every other word of each message and docblock is unchanged.
Lines changed: 191 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,191 @@
1+
/**
2+
* ObjectUI
3+
* Copyright (c) 2024-present ObjectStack Inc.
4+
*
5+
* This source code is licensed under the MIT license found in the
6+
* LICENSE file in the root directory of this source tree.
7+
*/
8+
9+
/**
10+
* objectui#10959 — what an unread `header-bar` key and an unread `body` drew,
11+
* stated for BOTH tiers. The sibling of objectui#10928, with a different code.
12+
*
13+
* Two families of published text said an authored value drew "no error, no
14+
* warning":
15+
*
16+
* - the `HeaderBarSchema` refusals of objectui#10387 (`title`, `logo`, `nav`,
17+
* `left`, `center`, `right`, `sticky`, `height`) and objectui#10286
18+
* (`variant`), on the zod face (message and `.describe()` are one string);
19+
* - the `body?: never` docblocks objectui#8284 put on the nine nodes whose
20+
* renderer reads `children` (`box`, `span`, `container`, `flex`, `stack`,
21+
* `grid`, `scroll-area` in `layout.ts`; `toggle`, `form` in `form.ts`),
22+
* which ship in the emitted `.d.ts`.
23+
*
24+
* The render half is true: the value changed nothing on the page and logged
25+
* nothing. The warning half was false. The parser tier's `validateTree`
26+
* (`@object-ui/sdui-parser`) answers a key its registration does not declare
27+
* with `unknown-prop`, and `header-bar` declares only `crumbs`, `search`,
28+
* `actions` and `rightContent`. It answers `body` the same way on these nine,
29+
* whatever its shape, because each of them declares the `children` input:
30+
* `checkRetiredBodyDialect` gives `not-a-container` only where that input is
31+
* missing, which is why objectui#10928's clause would be false here. So the
32+
* clause now names `unknown-prop`:
33+
*
34+
* refusal strings: "no render-time error or warning and no element; only the
35+
* parser tier's `unknown-prop` warning noticed it"
36+
* (`variant` says "no class" where the others say
37+
* "no element", as it did before)
38+
* docblocks: "rendered an EMPTY element with no render-time error or
39+
* warning; only the parser tier's `unknown-prop` warning
40+
* noticed it"
41+
*
42+
* ## Why this file pins the prose, and where the parser half lives
43+
*
44+
* `@object-ui/types` declares no workspace dependency and its tests import
45+
* none, so `@object-ui/sdui-parser` is not importable here without declaring
46+
* it (the same reason as objectui#10928's pin). The `body` half of the parser
47+
* behaviour is pinned in `packages/sdui-parser`: "the retired `body` spelling
48+
* follows the SAME predicate" in `containment-declared-slot-9910.test.ts`, and
49+
* "a `body` child list under a CONTAINER draws `unknown-prop` naming
50+
* `children`" in `body-dialect-6771.test.ts`. The `header-bar` half is the
51+
* generic undeclared-key branch of `validateTree`; no pin names `header-bar`
52+
* there. The live-registry reading taken for this change (every key above, on
53+
* `header-bar` and `ui:header-bar` and on the bare and `ui:` key of the nine,
54+
* with a render leg and a `not-a-container` control) is on objectui#10959's
55+
* pull request: a record of one run, not re-derived here.
56+
*
57+
* ## What is pinned, and what is deliberately not
58+
*
59+
* The clause as a substring. On the zod face: one `header-bar` key of each
60+
* clause form, read through its refusal with its code and path, then every
61+
* `header-bar` member whose refusal is one of these two retirements. On the TS
62+
* face: the `body` docblock of `BoxSchema` and of `FormSchema`, then every
63+
* docblock in `layout.ts` and `form.ts` that carries objectui#8284's sentence.
64+
* The rest of each string is NOT pinned; `header-bar-unread-keys-10387`,
65+
* `mirror-groups-cd-10286` and the objectui#8284 pins read it.
66+
*/
67+
68+
import { describe, it, expect } from 'vitest';
69+
import { readFileSync } from 'node:fs';
70+
import { join } from 'node:path';
71+
import { z } from 'zod';
72+
import { HeaderBarSchema } from '../zod/navigation.zod';
73+
74+
/** The clause the parser tier makes true — every site below ends on it. */
75+
const TAIL = "only the parser tier's `unknown-prop` warning noticed it";
76+
77+
/** The refusal strings' clause, in its two forms. */
78+
const ELEMENT_CLAUSE = `no render-time error or warning and no element; ${TAIL}`;
79+
const CLASS_CLAUSE = `no render-time error or warning and no class; ${TAIL}`;
80+
81+
/** The docblocks' clause. */
82+
const DOCBLOCK_CLAUSE = `rendered an EMPTY element with no render-time error or warning; ${TAIL}`;
83+
84+
/** The clauses they replaced — false about the parser tier. */
85+
const RETIRED_STRING_CLAUSE = 'no error, no warning';
86+
const RETIRED_DOCBLOCK_CLAUSE = 'with no error and no warning';
87+
88+
/** objectui#10928's code, which would be false on every site here. */
89+
const WRONG_CODE = '`not-a-container`';
90+
91+
/** The sentence that marks a docblock as one of objectui#8284's `body` refusals. */
92+
const MARK_8284 = 'Before objectui#8284 tombstoned it here, `body` was inherited-and-optional';
93+
94+
/**
95+
* The repo root, derived from THIS FILE's own location and never from the cwd
96+
* (objectui#7799): bare `import.meta.url`, taken apart by hand (the spelling
97+
* landed for objectui#7791, PR #7796).
98+
*/
99+
const SELF_DEPTH_BELOW_REPO_ROOT = 5; // packages / types / src / __tests__ / this file
100+
const REPO_ROOT = decodeURIComponent(new URL(import.meta.url).pathname)
101+
.split('/')
102+
.slice(0, -SELF_DEPTH_BELOW_REPO_ROOT)
103+
.join('/');
104+
const read = (relative: string): string => readFileSync(join(REPO_ROOT, relative), 'utf8');
105+
106+
const LAYOUT = 'packages/types/src/layout.ts';
107+
const FORM = 'packages/types/src/form.ts';
108+
109+
/** A docblock's text with its ` * ` continuations joined, as a reader sees it. */
110+
const joinDocblock = (doc: string): string => doc.replace(/\s*\n\s*\*\s?/g, ' ');
111+
112+
/** The docblock on `member` inside `export interface name`, joined. */
113+
function memberDocblock(src: string, name: string, member: string): string {
114+
const start = src.indexOf(`export interface ${name} `);
115+
expect(start, `interface ${name} not found`).toBeGreaterThan(-1);
116+
const end = src.indexOf('\n}', start);
117+
const body = src.slice(start, end);
118+
const at = body.search(new RegExp(`\\n\\s*${member}\\?:`));
119+
expect(at, `member ${name}.${member} not found`).toBeGreaterThan(-1);
120+
const before = body.slice(0, at);
121+
const open = before.lastIndexOf('/**');
122+
expect(open, `no docblock before ${name}.${member}`).toBeGreaterThan(-1);
123+
return joinDocblock(before.slice(open));
124+
}
125+
126+
describe('objectui#10959 — a header-bar refusal names the parser tier\'s `unknown-prop`', () => {
127+
const NODE = { type: 'header-bar' as const, crumbs: [{ label: 'Home' }] };
128+
const ARMS = [
129+
['title', 'My App', ELEMENT_CLAUSE],
130+
['variant', 'floating', CLASS_CLAUSE],
131+
] as const;
132+
133+
it.each(ARMS)('`%s` is refused by name, and the refusal names `unknown-prop`', (key, value, clause) => {
134+
const result = HeaderBarSchema.safeParse({ ...NODE, [key]: value });
135+
expect(result.success).toBe(false);
136+
const issue = result.success ? undefined : result.error.issues.find((i) => i.path.length === 1 && i.path[0] === key);
137+
expect(issue?.code).toBe('invalid_type');
138+
expect(issue?.path).toEqual([key]);
139+
expect(issue?.message).toContain(clause);
140+
expect(issue?.message).not.toContain(RETIRED_STRING_CLAUSE);
141+
expect(issue?.message).not.toContain(WRONG_CODE);
142+
});
143+
});
144+
145+
describe('objectui#10959 — every header-bar retirement carries the clause', () => {
146+
const shape = HeaderBarSchema.shape as Record<string, z.ZodType>;
147+
const members = Object.entries(shape)
148+
.map(([key, schema]) => ({ key, text: schema.description ?? '' }))
149+
.filter((m) => /^REFUSED \(objectui#(?:10387|10286), ADR-0049\)/.test(m.text));
150+
151+
it('the walk reaches both retirements (non-vacuity, by name rather than by count)', () => {
152+
const keys = members.map((m) => m.key);
153+
expect(keys).toContain('title');
154+
expect(keys).toContain('variant');
155+
});
156+
157+
it('none of them still says "no error, no warning", and each names `unknown-prop`', () => {
158+
const stale = members.filter((m) => m.text.includes(RETIRED_STRING_CLAUSE) || !m.text.includes(TAIL));
159+
expect(stale.map((m) => m.key)).toEqual([]);
160+
});
161+
});
162+
163+
describe('objectui#10959 — the `body?: never` docblocks name the parser tier\'s `unknown-prop`', () => {
164+
const sources = [
165+
[LAYOUT, read(LAYOUT)],
166+
[FORM, read(FORM)],
167+
] as const;
168+
169+
it.each([
170+
[LAYOUT, 'BoxSchema'],
171+
[FORM, 'FormSchema'],
172+
])('%s — `%s.body` carries the clause', (path, name) => {
173+
const doc = memberDocblock(read(path), name, 'body');
174+
expect(doc).toContain(MARK_8284);
175+
expect(doc).toContain(DOCBLOCK_CLAUSE);
176+
expect(doc).not.toContain(RETIRED_DOCBLOCK_CLAUSE);
177+
expect(doc).not.toContain(WRONG_CODE);
178+
});
179+
180+
it('every objectui#8284 `body` docblock in both files carries it (non-vacuity: both files reached)', () => {
181+
const stale: string[] = [];
182+
for (const [path, src] of sources) {
183+
const docs = (src.match(/\/\*\*[\s\S]*?\*\//g) ?? []).map(joinDocblock).filter((d) => d.includes(MARK_8284));
184+
expect(docs.length, `${path}: no objectui#8284 docblock found`).toBeGreaterThan(0);
185+
docs.forEach((d, i) => {
186+
if (d.includes(RETIRED_DOCBLOCK_CLAUSE) || !d.includes(DOCBLOCK_CLAUSE)) stale.push(`${path} #${i}`);
187+
});
188+
}
189+
expect(stale).toEqual([]);
190+
});
191+
});

‎packages/types/src/form.ts‎

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -877,8 +877,9 @@ export interface ToggleSchema extends BaseSchema {
877877
*
878878
* Before objectui#8284 tombstoned it here, `body` was inherited-and-optional
879879
* from {@link BaseSchema} — so authoring it here type-checked, parsed green
880-
* through `.passthrough()`, and rendered an EMPTY element with no error and
881-
* no warning. Per component, the channel a renderer does not read is now
880+
* through `.passthrough()`, and rendered an EMPTY element with no render-time
881+
* error or warning; only the parser tier's `unknown-prop` warning noticed it.
882+
* Per component, the channel a renderer does not read is now
882883
* tombstoned on both published faces (maintainer ruling, summon #17 decision
883884
* batch #2, 2026-09-07), and objectui#6771 has since retired `body` on
884885
* `BaseSchema` itself.
@@ -2131,8 +2132,9 @@ export interface FormSchema extends BaseSchema {
21312132
*
21322133
* Before objectui#8284 tombstoned it here, `body` was inherited-and-optional
21332134
* from {@link BaseSchema} — so authoring it here type-checked, parsed green
2134-
* through `.passthrough()`, and rendered an EMPTY element with no error and
2135-
* no warning. Per component, the channel a renderer does not read is now
2135+
* through `.passthrough()`, and rendered an EMPTY element with no render-time
2136+
* error or warning; only the parser tier's `unknown-prop` warning noticed it.
2137+
* Per component, the channel a renderer does not read is now
21362138
* tombstoned on both published faces (maintainer ruling, summon #17 decision
21372139
* batch #2, 2026-09-07), and objectui#6771 has since retired `body` on
21382140
* `BaseSchema` itself.

‎packages/types/src/layout.ts‎

Lines changed: 21 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -70,8 +70,9 @@ export interface BoxSchema extends BaseSchema {
7070
*
7171
* Before objectui#8284 tombstoned it here, `body` was inherited-and-optional
7272
* from {@link BaseSchema} — so authoring it here type-checked, parsed green
73-
* through `.passthrough()`, and rendered an EMPTY element with no error and
74-
* no warning. Per component, the channel a renderer does not read is now
73+
* through `.passthrough()`, and rendered an EMPTY element with no render-time
74+
* error or warning; only the parser tier's `unknown-prop` warning noticed it.
75+
* Per component, the channel a renderer does not read is now
7576
* tombstoned on both published faces (maintainer ruling, summon #17 decision
7677
* batch #2, 2026-09-07), and objectui#6771 has since retired `body` on
7778
* `BaseSchema` itself.
@@ -109,8 +110,9 @@ export interface TextSpanSchema extends BaseSchema {
109110
*
110111
* Before objectui#8284 tombstoned it here, `body` was inherited-and-optional
111112
* from {@link BaseSchema} — so authoring it here type-checked, parsed green
112-
* through `.passthrough()`, and rendered an EMPTY element with no error and
113-
* no warning. Per component, the channel a renderer does not read is now
113+
* through `.passthrough()`, and rendered an EMPTY element with no render-time
114+
* error or warning; only the parser tier's `unknown-prop` warning noticed it.
115+
* Per component, the channel a renderer does not read is now
114116
* tombstoned on both published faces (maintainer ruling, summon #17 decision
115117
* batch #2, 2026-09-07), and objectui#6771 has since retired `body` on
116118
* `BaseSchema` itself.
@@ -583,8 +585,9 @@ export interface ContainerSchema extends BaseSchema {
583585
*
584586
* Before objectui#8284 tombstoned it here, `body` was inherited-and-optional
585587
* from {@link BaseSchema} — so authoring it here type-checked, parsed green
586-
* through `.passthrough()`, and rendered an EMPTY element with no error and
587-
* no warning. Per component, the channel a renderer does not read is now
588+
* through `.passthrough()`, and rendered an EMPTY element with no render-time
589+
* error or warning; only the parser tier's `unknown-prop` warning noticed it.
590+
* Per component, the channel a renderer does not read is now
588591
* tombstoned on both published faces (maintainer ruling, summon #17 decision
589592
* batch #2, 2026-09-07), and objectui#6771 has since retired `body` on
590593
* `BaseSchema` itself.
@@ -712,8 +715,9 @@ export interface FlexSchema extends BaseSchema, FlexLayoutProps {
712715
*
713716
* Before objectui#8284 tombstoned it here, `body` was inherited-and-optional
714717
* from {@link BaseSchema} — so authoring it here type-checked, parsed green
715-
* through `.passthrough()`, and rendered an EMPTY element with no error and
716-
* no warning. Per component, the channel a renderer does not read is now
718+
* through `.passthrough()`, and rendered an EMPTY element with no render-time
719+
* error or warning; only the parser tier's `unknown-prop` warning noticed it.
720+
* Per component, the channel a renderer does not read is now
717721
* tombstoned on both published faces (maintainer ruling, summon #17 decision
718722
* batch #2, 2026-09-07), and objectui#6771 has since retired `body` on
719723
* `BaseSchema` itself.
@@ -747,8 +751,9 @@ export interface StackSchema extends BaseSchema, FlexLayoutProps {
747751
*
748752
* Before objectui#8284 tombstoned it here, `body` was inherited-and-optional
749753
* from {@link BaseSchema} — so authoring it here type-checked, parsed green
750-
* through `.passthrough()`, and rendered an EMPTY element with no error and
751-
* no warning. Per component, the channel a renderer does not read is now
754+
* through `.passthrough()`, and rendered an EMPTY element with no render-time
755+
* error or warning; only the parser tier's `unknown-prop` warning noticed it.
756+
* Per component, the channel a renderer does not read is now
752757
* tombstoned on both published faces (maintainer ruling, summon #17 decision
753758
* batch #2, 2026-09-07), and objectui#6771 has since retired `body` on
754759
* `BaseSchema` itself.
@@ -799,8 +804,9 @@ export interface GridSchema extends BaseSchema {
799804
*
800805
* Before objectui#8284 tombstoned it here, `body` was inherited-and-optional
801806
* from {@link BaseSchema} — so authoring it here type-checked, parsed green
802-
* through `.passthrough()`, and rendered an EMPTY element with no error and
803-
* no warning. Per component, the channel a renderer does not read is now
807+
* through `.passthrough()`, and rendered an EMPTY element with no render-time
808+
* error or warning; only the parser tier's `unknown-prop` warning noticed it.
809+
* Per component, the channel a renderer does not read is now
804810
* tombstoned on both published faces (maintainer ruling, summon #17 decision
805811
* batch #2, 2026-09-07), and objectui#6771 has since retired `body` on
806812
* `BaseSchema` itself.
@@ -1079,8 +1085,9 @@ export interface ScrollAreaSchema extends BaseSchema {
10791085
*
10801086
* Before objectui#8284 tombstoned it here, `body` was inherited-and-optional
10811087
* from {@link BaseSchema} — so authoring it here type-checked, parsed green
1082-
* through `.passthrough()`, and rendered an EMPTY element with no error and
1083-
* no warning. Per component, the channel a renderer does not read is now
1088+
* through `.passthrough()`, and rendered an EMPTY element with no render-time
1089+
* error or warning; only the parser tier's `unknown-prop` warning noticed it.
1090+
* Per component, the channel a renderer does not read is now
10841091
* tombstoned on both published faces (maintainer ruling, summon #17 decision
10851092
* batch #2, 2026-09-07), and objectui#6771 has since retired `body` on
10861093
* `BaseSchema` itself.

0 commit comments

Comments
 (0)