Skip to content

finding(types): 16 of the 41 keys #7735 de-defaulted publish a JSDoc @default that no registered renderer reads, and only 8 of 41 are pinned against the renderer #8318

Description

@claude

Found while implementing objectui#7735 (PR #8299) and its contract-review patch round. Unassigned, no labels — left for triage.

Measured on origin/main = 8f9d87a, plus the PR head.

What objectui#7735's ruling asked for, and what landed

The ruling's pin (ii) is: "JSDoc @default on each affected key equals the renderer fallback". That is the load-bearing half of option 乙 — once the zod mirror stops authoring values, the @default tag is the only place a default is still written down, and the renderer is the authority it is supposed to describe.

The first implementation report claimed that face was already satisfied. It was measured against the wrong reference: each tag was compared with the value the mirror used to write, not with what the renderer applies. Those two agreeing proves only that the docs copied the mirror. The contract review caught it and PR #8299 corrected four tags. This card is the part that round did not reach, recorded so the narrowing is not silently forgotten.

The re-measurement, against the renderer

All 41 de-defaulted keys, classified by what a registered renderer actually applies when the key is absent:

verdict n
tag agrees with what the renderer applies 19
tag misdescribed the renderer — corrected in PR #8299 4
no tag, deliberately (objectui#7361 / objectui#7734: two divergent consumers) 2
⚠️ no registered renderer reads the key at all — "equals the renderer fallback" has no referent 16

The 16:

CardSchema.variant                     @default 'default'
PageNodeSchema.isDefault               @default false
ActionSchema.level                     @default 'default'
ActionSchema.method                    @default 'POST'
ActionSchema.chainMode                 @default 'sequential'
ActionSchema.reload                    @default true
ActionSchema.close                     @default true
DetailSchema.showBack                  @default true
DetailSchema.loading                   @default true
CRUDDialogSchema.size                  @default 'default'
CRUDDialogSchema.closeOnOutsideClick   @default true
CRUDDialogSchema.closeOnEscape         @default true
CRUDDialogSchema.showClose             @default true
DetailViewSchema.showBack              @default true
DetailViewSchema.loading               @default true
AppComponentSchema.layout              @default 'sidebar'

CardSchema.variant is the sharpest of them and the one measured directly: both files that call ComponentRegistry.register('card', …)renderers/layout/card.tsx and renderers/layout/containers.tsx — contain no read of schema.variant anywhere. Its two siblings on the same interface are read (card.tsx:35 schema.clickable || !!props.onClick, :36 schema.hoverable || isClickable), which is the control that makes the absence a reading rather than a search that missed.

Until objectui#7735 landed, every one of the 16 had a .default() in the zod mirror doing something observable — substituting the value into a parsed document. That is gone now, so for these 16 the published @default describes nothing that runs.

Two distinct questions, deliberately not answered here

  1. Is the tag wrong, or is the key dead? A @default for a key no renderer reads is either a doc defect (delete the tag) or an ADR-0049 enforce-or-remove instance (the key itself is inert). Those have different fixes and different blast radii, and the second is a ruling question. objectui#7963 is the same shape for AlertDialogSchema, and objectui#4631 (pm:on-hold) is the general card about a component type having several disagreeing declared surfaces.
  2. Should the pin be general? PR fix(types,components): the zod mirrors stop authoring defaults #8299's pin is derived but row-by-row, and that is a measured decision rather than laziness: these renderers do not express defaults uniformly. A generic schema.x || 'lit' sweep scores grid.columns as "read, no literal fallback" and compares nothing — which is exactly how four wrong tags survived. Any general instrument has to model at least let baseCols = 2 (an initialiser), schema.centered !== false, a bare forward whose default is the absence of an affordance (withHandle), and a registry lookup that returns null (page.template). It also has to cope with two registrations claiming one type name: 'text' is registered by both renderers/basic/text.tsx and renderers/basic/elements.tsx, whose variant vocabularies do not even overlap, so "the renderer for this type" is not a function today.

What is pinned today, so the gap is legible

packages/types/src/__tests__/layout-default-jsdoc-7361.test.ts derives both sides off disk and covers 8 rows: ContainerSchema.maxWidth, FlexLayoutProps.align / direction / justify (objectui#7361 / objectui#7734), plus GridSchema.columns, TextSchema.variant, ResizableSchema.withHandle, PageNodeSchema.template (PR #8299), with ContainerSchema.centered and FlexLayoutProps.gap as negative controls. The other 33 of the 41 are unpinned: a future edit that moves a renderer's fallback away from its tag is invisible to CI outside those 8 rows.

Filed by an ObjectUI development agent while working objectui#7735. The dedupe read was bounded: open issues carrying domain:spec (47) and domain:ui (277), matched locally on @default / JSDoc / renderer fallback, each sweep with a control term that returned non-zero. ⛔ Not an exhaustive state=all search.


Generated by Claude Code

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    domain:specobjectui spec stream: fix lands on packages/types, schema corpus or spec pin coupling — spec lanefindingpackage: typespriority:p1

    Type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions