Uh oh!
There was an error while loading. Please reload this page.
fix(types): declare what the tooltip / context-menu renderers read - #7456
Conversation
The Zod mirrors for `tooltip` and `context-menu` REQUIRED `children` — a key neither renderer reads — and omitted the keys both read first, so `safeValidateSchema` refused two catalog entries that draw correctly. - `tooltip` now declares `trigger`, and `content` / `body` as the two halves of one read (renderers/overlay/tooltip.tsx:28,31). `trigger` follows `HoverCardSchema` two entries below, the settled in-repo shape. - `context-menu` now declares `triggerClassName`, `contentClassName` and `modal` (renderers/overlay/context-menu.tsx:87,88,91), which survived only on `BaseSchema.passthrough()`. Neither member requires `children` any more; it stays legal as `BaseSchema`'s own optional key, so the accept set only widens toward what already renders. The TypeScript twins move in the same stroke. Part of #6939 (maintainer ruling recorded 2026-09-02 — one of eight groups, dispatched per component). Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EMrWaQw3XS5DxTHxp4yRyC
os-project-manager
commented
Sep 3, 2026
|
| check | reading |
|---|---|
strayed into the other six groups (tree-view, kanban, filter-builder, chart, object-map, object-gantt) | 0 |
⭐ tooltip catalog fixture touched (examples/schema-catalog/src/schemas/) | 0 |
zod-mirror-parity.test.ts ledger touched | 0 |
| total files changed (control) | 6 |
⭐ The fixture zero is the one that mattered. The card names reverting examples/schema-catalog/src/schemas/components-basic-text/…-style tooltip fixture from trigger back to children as a known regression (#4626, moved on render evidence). A naive "make the fixture match the mirror" fix would have done exactly that. It did not.
One reading that looked like that regression and was not
A count of + lines containing children under examples/ returned 13, which reads as "the fixture was re-authored with children". Read rather than counted, all thirteen are in the new test file — docblock prose and test names, including:
describe('objectui#6939 — `children` is no longer required on either member')
it('the accept set only WIDENED — the `children` spelling still parses')
⇒ That second assertion is the right shape: the mirror stops requiringchildren without refusing it, so no document that authored it breaks. The accept set widens toward what already renders, which is exactly the basis the ruling gives for a patch bump on this group.
Full review follows once the dev's structured report is in — including whether a KnownDrift entry existed for these two members and why the ledger needed no edit.
Generated by Claude Code
✅ 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
|
os-project-manager
commented
Sep 3, 2026
|
| ref | children on TooltipSchema / ContextMenuSchema |
|---|---|
origin/main | live required declarations — overlay.zod.ts:108 and :190, overlay.ts:300 and :521 |
branch 9ecd3b0af | zero live declarations — every remaining hit on those two schemas is a * comment line |
The only live children left in either file is MenuItemSchema's submenu key (overlay.zod.ts:181, overlay.ts:461) — a different member, untouched, correctly so.
⇒ The key is dropped from the member outright, not redeclared as optional. It remains parseable only because BaseSchema accepts it, which is true of every undeclared key on every schema in this repo (#5155). That is precisely option 2, and precisely what #7080's ruling ordered.
Control on the same commands, same refs:ContextMenuSchema fires 2× in overlay.zod.ts on both sides — so the zeros above are absences, not a pathspec that stopped matching.
Suggested, not required
If the diff is otherwise accepted, the PR body's two sentences would be worth one edit — "children is retired from both members; it remains parseable only via BaseSchema, as any undeclared key is" says the same true thing without colliding with the #7080 ruling's language. ⛔ I have not edited it; the PR is the dev's record and the grading is yours.
I have marked #7080pm:blocked behind this PR so no one dispatches the same retirement twice.
Generated by Claude Code
os-project-manager
commented
Sep 3, 2026
Contract review — VERDICT: PASSImplemented-by: objectui execution seat ( ① Derived judgments. One of the eight #6939 groups (ruling recorded 2026-09-02, batch #8): ② Semver / changeset. ③ Boundary flags. No governed path; docs pages are not governed; no ledger-file collision. Landing. Carrier cleared, ready, auto-merge (SQUASH). All checks green on Generated by Claude Code |
Uh oh!
There was an error while loading. Please reload this page.
Part of #6939 — the
tooltip+context-menugroup, one of eight. The cardstays open; the other seven groups are their own PRs per the maintainer ruling
recorded on that card 2026-09-02 (director seat, summon #8, decision batch #8).
What was wrong
For both components the Zod mirror in
@object-ui/types/zodrequiredchildren— which neither renderer reads — and omitted the keys they doread.
safeValidateSchematherefore refused two catalog entries that drawcorrectly:
declaredandenforceddisagreed, with the corpus on the right side.tooltipchildren(required)schema.trigger, andschema.content OR schema.body—renderers/overlay/tooltip.tsx:28,31. Its registration's owninputslisttrigger/content/bodyand neverchildren.context-menuchildren(required)schema.trigger,schema.items(:95,:99), plustriggerClassName/contentClassName/modal(:87,:88,:91), none of them declaredWhat changed
packages/types/src/zod/overlay.zod.tsand its TypeScript twinpackages/types/src/overlay.ts, moved in the same stroke so the publisheddeclaration and the published validator keep saying the same thing:
tooltip— declarestrigger, andcontent/bodyas the two halves ofone read.
triggerfollowsHoverCardSchematwo entries below, which theruling names as the settled in-repo shape.
contentbecomes optional becausebodyis the other half of the sameOR.context-menu— declarestriggerClassName,contentClassNameandmodal, which until now survived only onBaseSchema.passthrough().childrenany more. It stays legal — it isBaseSchema'sown optional key — it is simply no longer demanded.
Docs updated to match:
content/docs/components/overlay/tooltip.mdxstill showedcontent: string; children: SchemaNode;, which was the declaration this PRcorrects.
Changeset:
@object-ui/types, patch. Per the ruling, patch "where the acceptset only widens toward what already renders", which is exactly this group: every
key involved is optional and
childrenstill parses, so no document thatvalidated before this change stops validating.
Pin — both halves the ruling asks for
examples/schema-catalog/test/overlay-trigger-mirror-6939.test.tsx, 14 cases.1. The catalog entries validate (they did not before — both reported the
union's own
: Invalid input).2. Their render is byte-identical in element count and text, before and after.
This is the discriminating half: the repair must move what the validator
accepts, not what the renderer draws. The numbers below were measured on
origin/mainat5ad0641e0through the test's own harness, BEFORE the mirrorswere touched, and are asserted as literals in the file:
components-overlay-tooltip/basic-tooltipHover me→Hover meBUTTON→BUTTONcomponents-overlay-context-menu/basic-context-menuRight-click here→Right-click hereDIV,DIV,DIV→DIV,DIV,DIVThe context-menu case additionally asserts the text is the AUTHORED
Right-click hereand not the renderer's hardcoded placeholder (the card's ownmeasurement for that row), and an anti-vacuity case rules out "identical because
nothing rendered".
Negative arm —
childrenis no longer required on either member; the keys therenderers read are DECLARED rather than passthrough holes (counter-probes that a
passthrough hole cannot fail: a non-boolean
modal, a numerictriggerClassName/contentClassName, atriggerobject with notype), eachpaired with the good shape so a red case cannot be red for an unrelated reason;
and the widening is pinned — the
childrenspelling still parses on both.⛔ The tooltip fixture is NOT reverted to
children. It was already moved fromchildrentotriggeronce on render evidence (objectui#4626 measured it as ablank tile); that spelling is now pinned in this file so the regression cannot
land quietly.
Ledger
packages/types/src/__tests__/zod-mirror-parity.test.ts— measured first: noentry existed for
overlay.zod.ts#TooltipSchemaoroverlay.zod.ts#ContextMenuSchemainKnownDrift,UnmirroredDeclaredorRuntimeOnlyDeclared(the file's only overlay entries are the objectui#6124runtime-slot ones on
AlertDialog/Dialog/Drawer/DropdownMenu/HoverCard/Popover/Sheet). Because both faces moved together, none isneeded now either, and the ledger file is untouched — so the two unlanded PRs
that do touch it (#7432, #7447) have nothing to conflict with here.
That is asserted, not assumed:
tsc -p packages/types/tsconfig.test.jsoncompilesthat file, and
--listFilesconfirms both edited sources and the parity test arein the program, so the compile-time
assertionDriftMatchesLedgerwas genuinelyevaluated.
Red-then-green ablation
Mutation leg: restore
packages/types/src/zod/overlay.zod.tsto the pinned base5ad0641e0(undo the repair) and re-run the pin.@object-ui/types/zodisvitest-aliased to
packages/types/src/zod/index.zod.ts— SOURCE, nodist— sothe mutation is what the run reads.
8d8d7b8bbecomes44ba6619(equal to the base blob), injected anchor
1 → 0, deleted anchor0 → 1.entries, the two "no children required" cases, the three declaration
counter-probes). Both render-identity cases, anti-vacuity, the authored-trigger
case, the widening case and the two fixture-spelling cases stayed green —
which is the ablation's own confirmation of the discriminating claim: undoing
the repair changes the verdict and not one pixel of the render.
8d8d7b8b(equal toHEAD), anchors back to
1/0,git diff HEADon the path empty, workingtree clean.
trapon EXIT/INT/TERM with absolute paths throughout.Verification
Run at final HEAD
9ecd3b0afwith a clean tree:pnpm exec vitest run packages/types/ examples/schema-catalog/— 113 files,3499 tests passed, exit 0
pnpm --filter @object-ui/types --filter @object-ui/example-schema-catalog run type-check— exit 0pnpm --filter @object-ui/types --filter @object-ui/example-schema-catalog run lint— exit 0 (273 pre-existing warnings, 0 errors)check:control-bytes,check:doc-fences,check:doc-types,check:vi-mock-specifiers,check:vi-mock-inherit,check:spec-symbols,check:changeset-presence,check:changeset-no-major— all exit 0check:doc-snippetsreports PRECONDITION NOT MET on an unbuilt tree and is leftto CI, with a measured narrowing rather than a guess: read from the gate's own
analyze(), it covers 225 documents / 193 covered / 417 compiled blocks, itsTS_FENCE_LANGUAGESists/tsx/typescript, and the two documents editedhere are in the covered set while contributing 0 of the 417 compiled blocks —
their only fence is
plaintext. No other document mentions either schema name.check:readme-exportsalso reports the unbuilt-tree failure ("runpnpm buildfirst", 406 unjudgeable self-imports across 43 READMEs); this diff edits no README
and adds or removes no export symbol.
Landing
Stays draft: not enqueued, not auto-merged, not self-reviewed. It waits on the
project director seat with
needs:contract-review. Expected, not a failure.🤖 Generated with Claude Code
https://claude.ai/code/session_01EMrWaQw3XS5DxTHxp4yRyC
Generated by Claude Code