feat(types)!: refuse both content channels on the E3 residual (nine object views, detail-view, email, password) and repair the shorthand Omit erasure (objectui#9256) - #10897
Conversation
…op the shorthand Omit erasing inherited members Part of objectui#9256 (the 15-key E3 residual the ruling on objectui#8284, Q2 A, moved onto that card). Twelve registrations have a published arm yet their renderer reads neither content channel: the nine object-* views, detail-view, email and password. Both body and children are now ?: never on the TypeScript face and a by-name refusal on the zod mirror (neitherContentChannel, a pair of retirementTombstone members), each kept a member so the parity ratchet's key sets stay equal. The message names what the node renders instead. InputShorthandSchema and UiCalendarSchema were spelled as a plain Omit over an interface carrying BaseSchema's index signature, which erased every inherited member on the published face. Both now inherit through OmitDeclared, a key-remapping Omit that keeps the named members; the two Omit COLLAPSE rows leave the MirroredUndeclared ledger and the inherited onChange runtime slot enters KnownDrift. br, hr and img are held: their only arm is the 38-tag HtmlElementSchema family, whose renderer draws children for the other 35. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DuWo5bdP9SdVebamn99GGk
…ding a call A computed spread in a zod arm is a shape check-handler-key-read-sites cannot follow, and the gate stops judging an arm whose member set it cannot resolve: the spread blinded it on all eleven arms and turned its detail-view onTabChange waiver stale. Each arm now declares body and children explicitly as retirementTombstone members fed one string from neitherContentChannelGuidance, so the gate reads every arm again (0 reads left unjudged). Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DuWo5bdP9SdVebamn99GGk
|
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: Isolated adversarial review of PR objectui#10897 (objectui#9256, family D, ① Derived judgmentsReads — each of the 12 reads neither channel, re-derived at the source.
Shape — PR objectui#9589's family-D shape on both faces. TS:
Collateral.
Producers.
② Semver level
③ Boundary flags
Implemented-by: VERDICT: PASS Generated by Claude Code |
One conflict, in packages/types/src/__tests__/zod-mirror-parity.test.ts: both sides rewrote the two KnownDrift header figures. Resolved by RECOUNTING the merged KnownDrift table with the test's own AST reader, not by picking a side: base 0c50f18 49 entries / 89 keys objectui#10874 (c30c8dd) drops ai.zod.ts#AIFormAssistSchema -1 entry / -2 keys objectui#9256 (this branch) adds form.zod.ts#InputShorthandSchema +1 entry / +1 key merged 49 entries / 88 keys Both header sites (the population bullet and the KNOWN_DRIFT ratchet restatement) now read 49 / 88, and the bullet keeps both histories in landing order. Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DuWo5bdP9SdVebamn99GGk
✅ 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: Delta review of PR objectui#10897 at the merge head, after record ① Derived judgmentsThe merge itself. Net change at the new head versus net change at the old head. The two unified diffs, normalised by dropping hunk headers and blob ids, differ in three places and nowhere else: the The recount, re-derived from the merged table with the compiler API (the
The dev's table is right in every cell. Both header sites read the merged figure — the population bullet "49 entries in Consistency with what landed on The changeset is byte-identical to the reviewed one and cites no ledger figure; every sentence checked in record ② Semver levelUnchanged: ③ Boundary flags
Implemented-by: VERDICT: PASS Generated by Claude Code |
Part of #9256
Clause-②: yes
Clause-②
yes, as the claim declared: twelve published arms stop accepting an authoredchildren, and two published TypeScript faces stop erasing the members they inherit. Both narrow an accept set; a contract review is owed before landing.The E3 residual that the maintainer's ruling on objectui#8284 (comment
5861449497, Q2 A) moved onto this card: keys with a published arm whose renderer reads neither content channel. It also carries the ruling's execution parameter 3, theInputShorthandSchema/UiCalendarSchemaTypeScriptOmiterasure. objectui#9256 stays open for the rest of family D.What changed
object-grid,object-form,object-kanban,object-map,object-tree,object-view,object-gantt,object-calendar,object-chart,detail-view,email,password.body?: neverandchildren?: never, each with a docblock naming what the node renders instead.bodyandchildrenare tworetirementTombstonemembers fed ONE string from the newneitherContentChannelGuidancebuilder inzod/tombstone.zod.ts. Both stay MEMBERS, sozod-mirror-parity's key sets stay equal.bodywas already refused on these arms (byBaseSchema, objectui#6771), except on theemail/passwordTypeScript face, which theOmiterased. It is restated becauseBaseSchema's refusal nameschildrenas the remedy, andchildrenis dead here too.Omiterasure repaired:InputShorthandSchemaandUiCalendarSchemanow inherit throughOmitDeclared(form.ts, not exported). It is a key-remapping mapped type: it drops exactly the named keys and keeps every other named member and the index signature.ui:calendargains no refusal of its own. Its face now re-exposes whatCalendarSchemadeclares, so the published TypeScript face refusesbody,childrenand amodeoutside the declared enum, which the erased face accepted. Its mirror (a.extend()of that one) already refused them.ui:calendarrenderer anyway (renderers/form/calendar.tsx, typedCalendarSchema). It readsdefaultValue,modeandvalue, and no channel.br,hr,img. See "Held, and the question it leaves" below.Per-key measurement, taken on
origin/main0c50f1863before any editInstrument. The TypeScript compiler API, ⛔ not grep. It builds one program per workspace package from that package's own
tsconfig.json: 40 programs over 1573 source files, on a BUILT tree (turbo build 42/42 first), with@object-ui/typesresolving topackages/types/dist. It files every.body/.childrenread (property access, string element access, object destructuring) under the declared type of its receiver.ButtonSchema1,DivSchema1,CardSchema1,ContainerSchema1 (eachchildren).body/childrenreads under that typeobject-gridplugin-grid:object-grid(+ consoleregisterLazyof the same plugin)ObjectGridRenderer(any) →ObjectGrid·ObjectGridSchemaobject-formplugin-form:object-formObjectFormRenderer(any) →ObjectForm·ObjectFormSchemaobject-kanbanplugin-kanban:object-kanban(+ lazy)ObjectKanbanRenderer(any) →ObjectKanban·ObjectKanbanSchemaobject-mapplugin-map:object-map(+ lazy)ObjectMapRenderer(any) →ObjectMap·ObjectMapSchemaobject-treeplugin-tree:object-tree(+ lazy)ObjectTreeRenderer(any) →ObjectTree·ObjectTreeSchemaobject-viewplugin-view:object-view(and theviewalias)ObjectViewRenderer(any) →ObjectView·ObjectViewSchemaobject-ganttplugin-gantt:object-gantt(+ lazy)ObjectGanttRenderer(any) →ObjectGantt·ObjectGanttSchemaobject-calendarplugin-calendar:object-calendar(+ lazy)ObjectCalendarRenderer(any) →ObjectCalendar·ObjectCalendarSchemaobject-chartplugin-charts:object-chart(+ lazy)ObjectChartBlock(any) →ObjectChart·ObjectChartSchemadetail-viewplugin-detail:detail-viewDetailViewRenderer(any) →DetailView·DetailViewSchemaemailui:email(field:emailstands down)anywrapper spreads the node intoInputRenderer·InputSchemaOmit) → both refusedpasswordui:password(field:passwordstands down)emailemailemailbrui:brany), void tag: passesundefinedas the childschema?.childrenread is behind the void-tag guard)any)hrui:hrimgui:imgThe residual count stays 15: no key reads
childrentoday. 12 are narrowed and 3 are held.any-typed receivers, attributed rather than assumed.any-typed. Each hop body was read: none contains a channel read.childrendestructured off internal components' own props (SchemaRendererpasses no node child as a React child);document.bodyanderr.body;TreeNode.childrenon the record hierarchyObjectTreebuilds;FeedItem.body;record:alert's ownprops.body, which is another registration.schema?.childrenread sits behindisVoid ? undefined : ….Delegation hosts, checked for pass-through. Every
SchemaRenderercall in the ten object/detail packages was traced. The node it renders is built one of three ways:ObjectForm/ModalForm/DrawerForm/TabbedForm/SplitForm/WizardFormall build theirformnode that way, and theformrenderer DOES drawchildren, which is why this was checked;DetailView'sheader/footer/ tabcontent,ObjectChart's drill-down table;object-*node —ObjectViewassemblesobject-kanban,object-calendar,object-gallery,object-timeline,object-gantt,object-map,object-treeandobject-chartfrom named keys, and every one of those reads neither channel (for gallery and timeline:packages/plugin-listandpackages/plugin-timelinehold no node-channel read).No host spreads its own node into a node that reads
children.Generic traversers (
validateChildrenin core,sdui-parservalidateTree, the metadata-admin preview canvases, the vscode validator) walk children to validate or preview. They render nothing and are node-agnostic, as for every row family D already holds.objectui#9910 cross-check. None of the 12 narrowed registrations declares a
childrenslot input: a grep over their registration files finds 0 hits, and the lit control ishtml-elements.tsx/div.tsx, which do.Producers.
pnpm census:body-dialect --keysover the 15, plusui:calendarandinput, withdiv/card/page/button/p/h1as lit controls in the same pass: 8981 files, 2744 candidate nodes.childrenon any of the 15.bodyonui:calendar: it was the family-D TRIPWIRE test line (test bucket), moved by this change.div170 /card183 /page47children.The
Omitrepair — measured on the BUILT d.tsA probe program under
packages/componentsresolved@object-ui/typestopackages/types/dist/index.d.ts(--traceResolution). It carried 15@ts-expect-errorpins (the 10 object/detailchildren,emailchildren,passwordbody,emaillabel: 42, and theui:calendarchildrenandmode: 'default'), a lit control (const n: number = 'x'), and 12 channel-free controls.dist/form.d.tsdeclaresOmitDeclaredlocally and both heritage clauses use it.Red on base, then green — one-shot, the restore proven by state
The predictions were written to a file BEFORE the mutation. The mutation was
git checkout 0c50f1863 -- THE-SEVEN-DECLARATION-FILES, with every test file at HEAD. It was proven by 7/7 blob hashes equal to BASE plus anchor counts (neitherContentChannel0,OmitDeclared0). The run sat undertrap … EXIT INT TERMwith absolute paths.14fd13c51)childrenfamilies + 12body-message rows + 1 nested rowtsc -p packages/types/tsconfig.test.jsonEqpins) in the new file, plus 3 inzod-mirror-paritynaming the two re-collapsed pairs and the staleKnownDriftrow; 0 elsewhereThe restore was proven by 7/7 blob hashes equal to HEAD,
git diff HEADempty andgit statusclean, both after the restore and at the end.bodyrows on the ten object/detail arms are GREEN on base, by design:BaseSchemaalready refusedbodythere. Only their MESSAGE changes, and the message rows are the ones that turn red.?: neveris erased before vitest runs, so the TypeScript half is read bytscalone. The vitest run cannot see it.Serial constraints
0c50f1863). PRs objectui#10714, fix(core,plugin-view,types): the density fold tests an own key; the flat-property warning and NamedListView's docblock stop naming retired channels (objectui#10868) #10883 and fix(plugin-view): the host delegation reads a named view's remaining protocol members off the named view (objectui#10758) #10884 were open then; all three have since merged, and PR objectui#10875 was the base.layout.ts(TabItem) andlayout.zod.ts(TabItemSchema): untouched, becausebr/hr/imgare held and neither file is edited.content-channel-family-d-9256.test.ts: the only edits are forced ones, clear of PR objectui#10714's hunks, which sit in the ListItem and Tabs sections:ui:calendarTRIPWIRE said "when the collapse is repaired this line goes RED … turn it back into a@ts-expect-errorpair". The repair fired it.uiCalendarBodyarray entry (32 → 31) and the now-unusedUiCalendarSchematype import.objectql.ts: the insertion afterObjectViewSchema's last member is clear of PR objectui#10883'sNamedListViewdocblock edit.object-view-unmirrored-keys-7779.test.ts(PR objectui#10884): untouched.5863631182):KnownDriftheader figures inzod-mirror-parity.test.tsand landed first (c30c8dd4c). This branch mergedmainat that commit (merge commit31bb63bcb, no rebase, no force-push) and recounted the figures from the merged table; see "Merge round" under Gates.git merge-treeof the merge head againstmainat6a7f24e92, which carries all of them, reports no conflict.zod/index.zod.tsand thepackages/cliratchet (objectui#10872) are untouched.Collateral that the repair and narrowing made true or false — each measured, none widened
zod-mirror-parity.test.ts:OmitCOLLAPSE rows (32 + 26 keys) leaveMirroredUndeclared. Its figures move from 4 / 60 to 2 / 2, and the class note records the emptying.any. So this is not the "declare the keys" remedy that ledger refuses.InputSchema'sonChangeruntime slot. It entersKnownDriftas inherited drift: one entry, one key. After the merge with PR objectui#10890 (which tookai.zod.ts#AIFormAssistSchemaout, one entry and two keys), the table holds 49 entries / 88 keys, and both header sites say so.KnownDriftand re-arms here when a multi-arm entry lands.object-view-spec-parity.test.ts:body/childrenare redeclared envelope keys onobject-viewnow. They are triaged intoSANCTIONED_LOCALas refusal-only surface, likeviewTabBar, and the declared-surface figure moves 24 → 26.CalendarSchema's texts on both faces said the TypeScriptOmit"collapses … and carries no member". That became false; they are corrected.Omitheritage (index.ts,form-barrel-mirror-9406.test.ts) are corrected.scripts/check-handler-key-read-sites.mjscaught my first spelling. It was a computed spread (...helper(…)) that the gate cannot resolve, so it stopped judging all eleven arms and itsdetail-viewonTabChangewaiver read stale. The fix, the second commit, declares both members explicitly. Now 49 / 49 reads are judged and 0 are left unjudged.Held, and the question it leaves
br/hr/imgread neither channel, but their only published arm isHtmlElementSchema: ONE object over 38 tags, whose renderer drawschildrenfor the other 35 (p,h1, …). Refusing the key on three tags means splitting that family arm, or refining it per tag. Both change a published contract's shape.5859897857) reads: "leaving the three void tags to the tier because their arm is the shared HtmlElementSchema family whose per-tag split was ruled out (objectui#9067)".childrenslot on a void tag, sovalidateTreereportsnot-a-container.That the brief listed them among the keys to narrow is recorded as a conflict in the report, ⛔ not resolved here by guessing.
Gates (at HEAD
14fd13c51, exit codes captured by redirect-then-capture; heavy runs through the shared verify lock)@object-ui/typesbuild (tsc + vite + dist completeness)@object-ui/typestype-check(tsc --noEmit+ examples +tsconfig.test.json)pnpm exec vitest run packages/types/(parity, node-slot, arm, mirror, family-D and the new pins)pnpm exec vitest run scripts/type-check: Donepnpm --filter @object-ui/types lintcheck:control-bytes·check:new-line-citations(0 new) ·changeset:check·check-changeset-presence·check:changeset-claims·check:pending-changeset-literalscheck:doc-types·check:doc-snippets·check:doc-examples·check:skill-examples·check:doc-fences·check:doc-example-ids(against the built types)check:handler-key-reads·check:component-surface-parity·check:prompt-keys·check:registry-bare-names·check:spec-symbols·check:readme-exports·pnpm check(CLI self-check)--testover the 14 pathsNOT MEASURED:
check:sdui-registration-pinsexits 2 without a console build. The diff touches no registration and nosideEffectsarray. Left to CI.pnpm testshards beyondpackages/typesandscripts/, plustest:distand E2E: left to CI.Merge round — head
31bb63bcb(mergesmainatc30c8dd4c)The one conflict was the two
KnownDriftheader figures inzod-mirror-parity.test.ts. It was resolved by RECOUNTING the merged table with the test's own AST reader, not by picking a side:KnownDrift0c50f1863ai.zod.ts#AIFormAssistSchemac30c8dd4c)form.zod.ts#InputShorthandSchema14fd13c51)31bb63bcbThe population bullet and the KNOWN_DRIFT restatement both read 49 / 88, and the bullet keeps both histories in landing order. The other ledgers read the same as before:
MirroredUndeclared2 / 2,UnmirroredDeclared12 / 84,RuntimeOnlyDeclared3 / 7,WiderThanDeclared6 / 7. The merge head differs frommainby exactly this PR's 14 files.31bb63bcbzod-mirror-parity+content-channel-e3-residual-9256@object-ui/typesbuild ·type-check(incl.tsconfig.test.json)pnpm exec vitest run packages/types/(incl. PR objectui#10890'sai-zod-arms-10859/ai-node-faces-agree-10874and the family-D file PR objectui#10714 edited)pnpm exec vitest run scripts/check:control-bytes·check:new-line-citations·changeset:check·check-changeset-presence·check:changeset-claims·check:pending-changeset-literals·check:handler-key-readsAcceptance notes — out of scope, not fixed here
inputreads neither channel as well.InputSchema: 0 channel reads, 17 keys read; the registration declares nochildrenslot.Omitcarries nothing") is gone with this repair: a tombstone onInputSchemanow propagates on both faces.PartialSchema's docblock inindex.tssays every generic re-spelling of itsOmitcollapses for the samekeyof Treason.OmitDeclaredis a generic spelling that does not: this PR measures it on two faces.Omitsubject. objectui#6397, that alias's card, is closed.InputSchemaas "family E, frozen" andDetailViewSchemaas unattributable. Both readings are superseded by this change.Generated by Claude Code