feat(types)!: refuse both content channels on six of the nine bare-name hold-outs (family D slice 2) - #9544
Conversation
…me hold-outs (objectui#9256) `text`, `image`, `icon`, `tabs`, `accordion` and `calendar` read NEITHER content channel, so `body` and `children` become `?: never` on the TypeScript face and a by-name `retirementTombstone` refusal on the zod mirror — kept a MEMBER so `zod-mirror-parity`'s key sets stay equal. These were held out of the earlier family-D slice because `ComponentRegistry.register` writes the bare-name fallback last-one-wins and which declaration governed a bare node was unmeasured. `check:registry-bare-names` measures it now, and every row was re-derived at this branch point rather than inherited. `button` was in the dispatched set and is deliberately NOT narrowed: its measured owner `ui:button` reads `schema.label || renderChildren(schema.body || schema.children)` — a LIVE fallback, which makes it family C and a behaviour change rather than a declaration repair. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011QreXiyMEqKLN4U5daMPVa
✅ 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: ① Derived judgmentsSix names narrow on both published faces. Verified on the branch, per declaration:
⭐ This run IS the verification the container restart destroyed. The commit ⭐⭐ Both halves were re-derived SEPARATELY, and that is the whole point. My dispatch conflated them and it cost a name:
⭐ And the reason those zeros are readings: all 228 ⛔ ② Semver level
③ Boundary flags⛔ None raised. The narrowing is the deliverable and its blast radius was measured, not asserted. ⭐ The authoring sweep caught a silent zero rather than shipping one. The shipped ⭐⭐ Two predictions came out WRONG and are reported as wrong — which is what makes the rest of the ablation worth reading:
Coverage proven rather than assumed: Implemented-by: VERDICT: PASS ⛔ On the one ✅ LandingEVERY check green on
Generated by Claude Code |
Part of #9256 — slice 2 of family D. This slice narrows SIX names and leaves
button,list,timeline,inputandapp-schema-rendererwhere they are; the card stays open and the PM seat ends it.text,image,icon,tabs,accordionandcalendarread NEITHER content channel, sobodyandchildrenbecome?: neveron the TypeScript face and a by-nameretirementTombstonerefusal on the zod mirror — each one kept a MEMBER of the mirror shape, sozod-mirror-parity's key sets stay equal.This branch carried one commit from a run that a container restart killed before it could verify anything or report. Whether any gate had been run was UNKNOWN, so everything below was derived fresh at this branch point and nothing was inherited from the commit or from the dispatch.
buttonis NOT narrowed — re-derived, and the dispatch was wrong to include itThe dispatch listed seven names.
button's measured ownerui:buttonrendersschema.label || renderChildren(schema.body || schema.children)inpackages/components/src/renderers/form/button.tsx— a LIVE fallback. That makes it family C, which this card excludes as a maintainer decision, not family D. Settling ownership (objectui#9264) does not settle readership, and only readership licenses a tombstone.A LIVE CONTROL in the pin test keeps
buttonparsing both channels, so the rows above stay a reading about the six that moved.Re-derivation 1 — ownership, at this branch point
pnpm check:registry-bare-names --table(exit 0), scanning 1622 source files / 425 registration claims:skipFallback: true)textui:text(sole)element:text·field:textimageui:image(sole)element:image·field:imageiconui:icon(sole)action:icontabsui:tabs(sole)page:tabsaccordionui:accordion(sole)page:accordioncalendarview:calendar(agreed, 2 claimants naming ONE full type)ui:calendarbuttonui:button(sole)action:button·element:buttonRe-derivation 2 — readership, with the TypeScript CHECKER and not grep
A one-time compiler-API sweep filed every
.body/.childrenread under the DECLARED TYPE of the receiver, over one program built from the repo-roottsconfig.json— 4608 root names, 5043 source files, 17 unresolved-module diagnostics.anypopulation read, or it is not a reading. 470 channel reads resolve to ananyreceiver —anyreads as NEITHER, exactly the shape that hides a hit. 228 of them fall under the renderer / field / plugin trees and every one was attributed:html-elements.tsxandsemantic.tsxreadschema.children ?? schema.bodyLIVE, but their tag lists areh1…q,img,hr,brand the seven semantic sectioning tags — none of the six (imgis notimage).containers.tsx—collectRelatedLists/containsAttachmentsNodeare genericanynode walkers with no registration; the reads insidePageCardRenderer,PageSectionRenderer,PageFooterRendererandPageSidebarRendererbelong to keys outside this slice.PageAccordionRenderercontains no channel read at all, which is the stand-down claimant foraccordion.PageTabsRendererandtabs.tsxread(it as any).childrenanditem.content || (item as any).body— the ITEM channel, filed under the item and not the node. An instrument that attributed that to the node would have madetabsa body reader and this whole row a mistake, so the item channel is pinned as still live.childrenin render helpers,init.bodyonfetch, and list-item reads.Generic traversers were checked separately rather than ignored:
validateChildreninpackages/core/src/validation/schema-validator.tsreadsschema.children || schema.bodyoffSchemaNodeUnderValidation, and the nineBaseSchema-typed reads are all the held-outsidebarfamily. Neither is a per-declaration read.SchemaRendererdestructureschildrenandbodystraight out of the props bag it spreads, so neither key reaches a component by another route — which is why an authored value rendered NOTHING: no error, no warning, no element.Re-derivation 3 — does anything AUTHOR the tombstoned channel?
pnpm census:body-dialectis structurally blind to all six: itsALL_KEYScontains none of them, so its zero is a population artifact and NOT a reading. This was caught, not shipped as a green. The same scanner was re-run over the six as its population, withdiv/card/page/buttoncarried as lit controls in the same pass:textbodyschema-reference.mddiv2 /card7 /page2div71 /card50 /page44Same scanner, same file, one commit apart: 4 becomes 0. That is what makes the zero a reading. Across the whole tree the only authored channel left on the six is inside this card's own pin test (the
@ts-expect-errorfixtures, by design) and one filler node inpackages/cli/src/__tests__/check-schema-marker.test.tswhose assertion is about an unrelated unregistered root type — noted below, and green.Ablation — direction predicted in writing FIRST, and one prediction was wrong
Mutation proved on disk by anchor count AND blob hash; restore proved by state (
git diff HEADempty AND blob hash matching the HEAD blob); every leg under atrap ... EXIT INT TERMwith absolute paths; working tree clean at the end. Both readers resolve the mutated file through a relative source import, so nodistround-trip stands between the mutation and the verdict.bodytombstone member onTextSchematsc -p tsconfig.test.jsonzod-mirror-parity.test.ts, on the pair name and on the keybodyitself.omit()both keys off the mirrortsc -p tsconfig.test.jsonbody?: neverfrom the TS facetsc -p tsconfig.test.jsonUnused '@ts-expect-error' directiveat the pinned line, plus TS2322 at parityTwo corrections, both recorded before the re-run rather than after:
zod-mirror-parity. Wrong: the zodBaseSchemaalready declaresbodyandchildrenas members, so deleting a tombstone reverts the key to BaseSchema's permissive union instead of removing it. The key set stays equal and parity is unmoved.zod-mirror-parity.test.tsis a type-level ratchet whose assertions arenever-typed declarations read bytsc, and a vitest run of that file exercises only its runtime census. Re-run withtscon the identical mutated tree it is RED. A1 and A2 together are what make "kept a MEMBER" load-bearing rather than decorative: delete the member and the type drifts, omit the key and the key sets diverge.Gates
Exit codes captured by redirect-then-capture, never through a pipe. Heavy runs serialized through the shared verify lock.
turbo run type-check --force— 81/81 tasks,Cached: 0 cached, 81 totalpnpm lint— 47/47 tasks, 0 errorspackages/typesui:calendarand four live controls all livepackages/clipackages/componentspnpm check(the steplint.ymlruns; it validates in-repo schemas through the narrowed union)typeliteralscheck:registry-bare-names·check:sdui-registration-pins·check:prompt-keyspackages/types/tsconfig.jsondoes not include the pin test andtsconfig.test.jsondoes — counted withtsc --listFiles(1 vs 0) rather than assumed, which is what makes the@ts-expect-errorblock a real assertion underpnpm type-check.Not run locally and left to CI: the 4-way
pnpm testshards beyond the three packages above,test:dist, E2E, and Bundle Analysis.Acceptance notes — out of scope, not fixed here
scripts/body-dialect-census.mjs's--jsonoutput emits onlylabel/root/filesScanned/hitsand declares no key population, while its own header promises "Known limits (stated so a zero is readable)" and lists template literals and YAML but not this one. A consumer asking it about a key outsideALL_KEYSgets a confident zero indistinguishable from a real one. Reported for triage; successor: the next family-D slice, which will ask it the same question.zod-mirror-parity.test.tsunder vitest exits 0 on a tree whose ratchet is violated — measured above. The obvious command gives a green that says almost nothing. Reported for triage.packages/cli/src/__tests__/check-schema-marker.test.tscarries a filler{ type: 'text', body: 'hi' }inside a node whose root type is deliberately unregistered. It is an instance of the now-refused spelling, it is not load-bearing for that test's assertion, and the wholepackages/clisuite pluspnpm checkare green with it. Noted, not filed.Instruments, their outputs and the written predictions live in this run's scratchpad; every figure above is a reading taken on this branch, not a figure carried from the card or the dispatch. Generated by the
os-devseat in Claude Code sessionsession_011QreXiyMEqKLN4U5daMPVa.Generated by Claude Code