Skip to content

docs(blocks): correct block-schema.mdx to the declared vocabulary, drop the phantom slot node - #5937

Merged
os-zhuang merged 2 commits into
mainfrom
claude/issue-4895-block-schema-docs-truth
Aug 24, 2026
Merged

docs(blocks): correct block-schema.mdx to the declared vocabulary, drop the phantom slot node#5937
os-zhuang merged 2 commits into
mainfrom
claude/issue-4895-block-schema-docs-truth

Conversation

@os-zhuang

@os-zhuang os-zhuang commented Aug 24, 2026

Copy link
Copy Markdown
Contributor

Part of #4895

Carries the maintainer ruling recorded on that card (comment 5339693569, 2026-08-19, 「全部接受」): Option B — docs-truth fix, the block family re-scoped as type-level. Option A (build renderers) was rejected on zero pull; Option C (retire the family) is deferred. Neither is implemented here, and neither is argued for.

Reference keyword is deliberately Part of, not a closing keyword: the ruling leaves Option C open, to be revisited if a later liveness pass shows the published types inert externally. The measurement below strengthens that future case rather than settling it, so the card should stay open for the PM seat to judge.

What was wrong

content/docs/blocks/block-schema.mdx:254 taught this inside BlockSchema.template:

{
  type: 'slot',
  name: 'content'
}

template is typed SchemaNode | SchemaNode[], so that snippet sat on the render path — and nothing registers slot. A reader who copied it got the renderer's OBJUI-001 "Unknown component type" panel. That node is deleted; the page now teaches slotContent, the key BlockSchema and BlockInstanceSchema actually declare.

The measurement that changed how this is written

The ruling says "teach slotContent". Before writing that, I measured whether slotContent is consumed by anything — a renderer, a hook, an adapter. It is not.

Every occurrence in the repository, excluding node_modules and dist:

site what it is
packages/types/src/blocks.ts:201 BlockSchema.slotContent declaration
packages/types/src/blocks.ts:377 BlockInstanceSchema.slotContent declaration
packages/types/src/zod/blocks.zod.ts:77 Zod mirror
packages/types/src/zod/blocks.zod.ts:134 Zod mirror
content/docs/blocks/block-schema.mdx:297 this page
scripts/check-doc-component-types.mjs:283 the exemption reason this PR deletes

Zero renderers, zero hooks, zero adapters. The same holds for slots and template on this family — outside packages/types (the interfaces, the Zod mirror, and that package's own parse test) nothing reads them.

So the page does not present slotContent as the working path. It documents it as the declared path and states plainly that it is not yet consumed. Rewriting one phantom into a second phantom is the failure this card exists to close, so the page carries a status callout up front rather than implying a runtime that does not exist.

Two supporting measurements are written into the page because they are what a confused reader needs:

  • The four SchemaExample demos the page embeds are ordinary registered component trees (card, flex, stack, text, icon, button, badge). None carries type: 'block', slots or slotContent — nothing on the page was ever exercising the block vocabulary.
  • The slot system that is wired end to end is a different family: slotted record pages (kind: "slotted", page.slots), consumed by usePageAssignment, PageBlockCanvas and PageBlockInspector, documented at content/docs/guide/slotted-pages.md. The page now links there so the two slots spellings are not conflated.

Full vocabulary audit, not just slot

Every type literal the page teaches, checked against the gate's derived registered-key universe (659 keys). Line numbers are pre-change.

value lines registered? vocabulary action
block 44, 140 no BlockSchema discriminant keep, exempted — a definition
block-editor 356 no BlockEditorSchema discriminant keep, exempted
block-instance 283 no BlockInstanceSchema discriminant keep, exempted
block-library 320, 374 no BlockLibrarySchema discriminant keep, exempted
boolean 62, 192 yes BlockVariable.type data type no change
button 258 yes SDUI node no change
card 223 yes SDUI node no change
div 75, 227, 239 yes SDUI node no change
icon 231 yes SDUI node no change
list 300 yes SDUI node no change
slot 254 no nothing — phantom, on the render path deleted
string 56, 162, 170, 177, 185, 199 no BlockVariable.type data type keep, exempted
text 243, 249 yes SDUI node no change

slot is the only unregistered value that named a renderable node. The other five unregistered values are each a discriminant of a declared interface or a variable data type, and each keeps a live exemption. So there was no second slot-shaped defect to sweep up.

One incidental observation, not a defect on this page and not changed: boolean at :62 and :192 is a BlockVariable.type data type that happens to collide with a registered component key, so it passes the gate's flat rule without needing an exemption. The page is correct; the gate's judgment there is a coincidence rather than a check.

Gate calibration — proving the silence is a measurement

Removing the exemption is only meaningful if check-doc-component-types.mjs actually reads this file. A gate that is silent because it never looked is not a passing gate, so this was calibrated rather than assumed. The mutation was confirmed on disk by grep count, never by the editing tool's exit code, and the script carried a trap ... EXIT INT TERM restore.

Mutation leg — rewrite the registered type: 'card' node at :223 to a value nothing registers:

"type: 'card',"                 1 -> 0   (deleted text)
'objui-4895-calibration-probe'  0 -> 1   (injected text)

Gate exit code, captured before any pipe: 1

content/docs/blocks/block-schema.mdx:223  [unregistered-doc-type]  type 'objui-4895-calibration-probe' (plaintext)
    type: 'objui-4895-calibration-probe',

Restore leg — probe absent, anchor back, git status clean for the file. Gate exit code: 0, ✅ Every documented component type is registered.

The gate reads this page.

The two halves are a matched pair

Both failure directions were exercised, so neither half is passing by accident:

  • Doc corrected but the exemption put backstale-exemption: content/docs/blocks/block-schema.mdx -> slot no code block in that file spells this type any more.
  • Exemption dropped but the phantom node put back → exit 1, content/docs/blocks/block-schema.mdx:305 [unregistered-doc-type] type 'slot' (plaintext)

Only both halves together are green.

Gate ledger

The slot entry in DOC_TYPE_EXEMPTIONS pointed at this card and is dropped, as the ruling requires. With the phantom node gone it would itself report as stale-exemption, so it is deleted rather than re-pointed; a comment records why, so the next reader does not re-add it. The three terse family reasons (block-instance / block-library / block-editor) are re-pointed at the ruling's framing — each now records that the schema is absent from AnySchema and has no renderer, which is the fact the gate's own standard asks an exemption reason to name.

Counters move coherently: exempted 139 → 138 (one entry gone), registered 743 → 744 (the new type: 'text' site), code blocks 1055 → 1056.

Verification — union run at ca35295a9 (final commit)

Exit codes captured before any pipe; verdicts quoted from each gate's own output.

gate exit verdict line
check-doc-component-types 0 Every documented component type is registered.
check-doc-links 0 Links are valid across 13 scan roots.
check-control-bytes 0 check-control-bytes: OK (scanned 4929 tracked text file(s); skipped 85 binary).
check-changeset-presence 0 No source of a released package changed in this range, so no changeset is owed.
check-changeset-fixed 0 All workspace packages are in the changeset fixed group.
check-changeset-no-major 0 No changeset declares a major bump.

scripts/__tests__/check-doc-component-types.test.ts34 passed (34), run at ca35295a9 from the repo root. Its three live-table assertions were also evaluated directly against this diff: stale-exemption findings []; exempted 138 (asserted > 50); declaration count 82 → 81 (asserted > 20).

eslint scripts/check-doc-component-types.mjs --no-inline-config --format json — 1 file linted, 0 errors, 0 warnings.

Declared narrowing: check-doc-snippet-types

Not run to completion — it needs a full monorepo build. The narrowing is a measurement, taken with that gate's own scanner, not an assumption:

  1. Its fence-language set is TS_FENCE_LANGUAGES = new Set(['ts', 'tsx', 'typescript']) (its own source, line 224).
  2. scanFences() on this page returns blocks=0, markers=0 in both states — at HEAD~1 and on the working tree. Every fence on the page is plaintext (10 → 11), and the one I added is plaintext too.
  3. The page is not named in UNGATED_DOCS, so no ledger entry of mine can go stale.

The gate collects zero blocks from this page either way, so this diff cannot change its verdict. CI runs it in full regardless.

Changeset

.changeset/block-schema-docs-truth-4895.md, empty frontmatter — docs and a gate ledger only, no released package src/ is touched, declared explicitly rather than left undeclared. objectui has no skip-changeset label; the empty-frontmatter changeset is this repo's declaration mechanism.

Deliberately not done

  • No renderers built for block-library / block-editor / block-instance (Option A, rejected on zero pull).
  • Nothing retired from packages/types (Option C, deferred). No published type is touched.
  • Best Practices and Use Cases left as-is. Both still read somewhat aspirationally, but the status callout now governs the whole page, and gutting them is beyond the ruling's scope. Flagging rather than silently widening the diff.

Generated by Claude Code

claude added 2 commits August 24, 2026 02:17
)

Carries the recorded maintainer ruling on #4895 (Option B: docs-truth fix,
family re-scoped as type-level).

- Delete the phantom `type: 'slot'` node from the Complete Example template.
  Nothing registers `slot`, so a reader who copied it got OBJUI-001.
- Teach the declared `slotContent` path instead, and state plainly that it is
  declared-but-not-yet-consumed: nothing reads `slots` / `slotContent` /
  `template` at runtime.
- Frame `BlockSchema` as a definition and drop the component-schema framing for
  `block-library` / `block-editor` / `block-instance`.
- Disambiguate from the slot system that IS wired end to end (slotted record
  pages), which is an unrelated vocabulary.
- Drop the now-stale `slot` entry from DOC_TYPE_EXEMPTIONS in
  scripts/check-doc-component-types.mjs, and re-point the three terse family
  reasons at the ruling's framing.

Option A (build renderers) is rejected on zero pull; Option C (retire the
family) is deferred. Neither is implemented here.
Empty frontmatter: docs and a gate ledger only, no released package `src/`
is touched. Declared explicitly rather than left undeclared.
@os-zhuang
os-zhuang marked this pull request as ready for review August 24, 2026 02:50
@os-zhuang
os-zhuang added this pull request to the merge queue Aug 24, 2026
Merged via the queue into main with commit d719f84 Aug 24, 2026
22 checks passed
@os-zhuang
os-zhuang deleted the claude/issue-4895-block-schema-docs-truth branch August 24, 2026 02:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants