Skip to content

docs(fields): annotate the remaining 22 Field Schema blocks against the exported *FieldMetadata (#6138 PR 2) - #6162

Merged
yinlianghui-tw merged 2 commits into
mainfrom
claude/issue-6138-fields-schema-pr2
Aug 24, 2026
Merged

docs(fields): annotate the remaining 22 Field Schema blocks against the exported *FieldMetadata (#6138 PR 2)#6162
yinlianghui-tw merged 2 commits into
mainfrom
claude/issue-6138-fields-schema-pr2

Conversation

@yinlianghui-tw

@yinlianghui-twyinlianghui-tw commented Aug 24, 2026

Copy link
Copy Markdown
Collaborator

Fixes#6138 — batch 2 of 2, the remaining 22content/docs/fields pages. Batch 1 (#6146) has merged; it added the shared widget-props.mdx page and converted the other four, so the card is complete with this one.

origin/main merged in at 7eb632749 (merge commit, no rebase, no force-push). The 22 links to /docs/fields/widget-props that were red while this branch predated #6146 are green now — check-doc-links prints Links are valid across 15 scan roots at exit 0, and the doc-gate suites are Test Files 3 passed (3). The diff itself is unchanged; the merge only brought main under it.

What was wrong

Each of these pages opened with a ## Field Schema block that declared an interface of its own. A self-declared interface with no imports type-checks no matter what it says, because nothing in it refers to anything the packages export, so check-doc-snippet-types reported the page green while being structurally unable to see whether the documented shape matched the shipped one.

Each block is now a literal annotated with that field type's exported *FieldMetadata, judged by the sealed type's excess-property check.

Sealedness, verified per type rather than inherited

⭐ This mechanism only works against a sealed type. On an open one — a type ending in [key: string]: any — an annotated literal accepts any key, so converting would turn an uncompiled vacuous block into a compiled vacuous block and raise blocks-to-compile while catching nothing. That is the measured state of the components lane (#6143).

All 26 types this batch annotates against are sealed: the 22 field metadata types plus SelectOptionMetadata, GridColumnDefinition, UploadedFileMetadata and LookupColumnDef. Verified by the nonsense-key control on each type individually — a literal carrying thisKeyIsCompleteNonsense produces TS2353 naming the key — and by reading index-signature info off each type through the compiler (none, on all 26). TextFieldMetadata and BaseFieldMetadata were probed alongside as lane controls and are sealed too.

The harness carries a negative control, and that is what makes the 26 verdicts measurements rather than a uniformly silent instrument. In the same run, against the components lane's types, it reports the opposite — so it demonstrably can report open.

typeindex signaturesnonsense-key controlverdict
the 22 field metadata types + the 4 helper typesnoneTS2353 naming the keySEALED (26/26)
ButtonSchema (negative control)stringno diagnostic at allOPEN
BaseSchema (negative control)stringno diagnostic at allOPEN

The vacuity, demonstrated and closed on a page from this batch

Page: content/docs/fields/select.mdx. Mutations grep-confirmed on disk before any gate result was read, each leg under a trap … EXIT INT TERM restore, with the fix committed first.

Leg A — the pre-fix self-declared block restored from main (228909995), wrong key injected:

injected marker 'tooltip' occurrences: 1
108: tooltip?: string; // MUTATION: no exported type declares this
pre-fix form still in place ('interface SelectFieldSchema' occurrences): 1
Semantic phase: 249 of 249 block(s) judged, 0 failed.
Every covered documentation snippet compiles against the built types.
os-verify-lock: VERDICT command-exit 0

A key no shipped type declares passes green. That is the vacuity.

Leg B — the post-fix annotated literal, same page, same key:

injected marker 'tooltip' occurrences: 1
109: tooltip: 'hover me',
post-fix form in place ('SelectFieldMetadata' occurrences): 3
pre-fix form absent ('interface SelectFieldSchema' occurrences): 0
[semantic] content/docs/fields/select.mdx:109:3 TS2353: Object literal may only specify
known properties, and 'tooltip' does not exist in type 'SelectFieldMetadata'.
Semantic phase: 249 of 249 block(s) judged, 1 failed.
os-verify-lock: VERDICT command-exit 1

Leg C — the nested option literal alone, which is new in this batch: the option objects are judged against SelectOptionMetadata, so a wrong key inside one reddens too.

injected nested marker occurrences: 1
114: { label: 'Locked', value: 'locked', disabled: true, badge: 'new' },
no outer mutation present ('tooltip' occurrences): 0
[semantic] content/docs/fields/select.mdx:114:57 TS2353: Object literal may only specify
known properties, and 'badge' does not exist in type 'SelectOptionMetadata'.
Semantic phase: 249 of 249 block(s) judged, 1 failed.
os-verify-lock: VERDICT command-exit 1

⚠️Do not "simplify" legs B and C back into one run. A first attempt injected both keys at once and the gate reported only the nested one: TypeScript suppresses the outer excess-property error when a nested literal already fails. That run was discarded as conflated, and one key per leg is what makes B and C two independent readings instead of one reading counted twice.

Restore leg, confirmed on disk:tooltip 0, badge: 'new' 0, interface SelectFieldSchema 0, SelectFieldMetadata 3, and git status --short / git diff HEAD --stat both empty.

Every divergence checked against its renderer

A key the renderer reads but no type declares is filed, not deleted; a key nothing reads and no type declares goes.

findingevidencedisposition
dependsOn on select metadataSelectField.tsx:98const dependsOn = (config as any)?.dependsOn ?? dependsOnProp;, and no exported metadata type declares it (BaseFieldMetadata declares the snake_case depends_on)filed as #6153, page points at the card
description on a lookup's static optionsLookupField.tsx:526 reads opt.description; LookupFieldMetadata.options is declared SelectOptionMetadata[], which has no descriptionfiled as #6153 (same card, same class)
location value { latitude, longitude }LocationField.tsx:15 / :35 produce and consume it; no exported type declares the value shapefiled as #6154, page describes it in prose and links the card
per-column editable on gridzero .editable reads in GridField.tsx; declared by neither GridColumnDefinition nor the widget's own GridColumnremoved
lookup option _id / nameoptions are matched by value and labelled by label; those two keys are read off records, not optionsremoved

Four documentation errors the conversion forced out: grid.mdx gave a column width as a string (it is a number of pixels) and documented an editable key that does not exist; formula.mdx offered currency as a return_type where the shipped union is 'text' | 'number' | 'boolean' | 'date' | 'datetime'; user.mdx documented the value as a user object where the field stores the user's id. No type, export or union member was minted for any of them.

Out of scope here and untouched: #6140 remains open.

Verification at the merged head

Count identity, predicted in writing before measuring (predicted-merged.txt, timestamped 21:54:18Z, written after the new baseline was taken and before the merged head was measured). The baseline moved because #6146 landed, so the pre-merge numbers are dead: on origin/main at 7797e3b74 the gate reads 223 documents / 179 covered (74 with ts/tsx) / 44 ungated, Covered blocks: 361 — 250 to compile, 111 fragments — exactly the pre-merge baseline plus widget-props.mdx's one document and two blocks. My delta on top is unchanged by the merge (which touched none of my 22 pages): 21 conversions one-block-for-one-block, lookup.mdx becoming two blocks, file.mdx keeping one block with two consts, no document entering or leaving, no FRAGMENT_MARKER.

new baseline (7797e3b74)predictedmerged head (7eb632749)
documents scanned223223223
covered (holding a ts/tsx block)179 (74)179 (74)179 (74)
ungated444444
covered blocks361362362
to compile250251251
declared fragments111111 (unmoved)111

Gate union at the merged head 7eb632749, clean working tree, under the shared verify lock, each exit code captured before any pipe:

__EXIT_build=0
__EXIT_doc_snippets=0
__EXIT_doc_links=0
__EXIT_doc_types=0
__EXIT_control_bytes=0
__EXIT_fence_languages=0
resolution Module name '@object-ui/types' was successfully resolved to
'/home/user/objectui-6138-pr2/packages/types/dist/index.d.ts'
sentinel importing 'ThisNameIsDefinitelyNotExported' produced 1 diagnostic(s) (TS2305)
positive importing 'ComponentSchema' produced 0 diagnostic(s)
undeclared importing '@floating-ui/react-dom' … produced 1 diagnostic(s) (TS2307)
Scanned 223 document(s): 179 covered (74 of them hold a ts/tsx block), 44 ungated
Covered blocks: 362 — 251 to compile, 111 declared fragment(s).
Semantic phase: 251 of 251 block(s) judged, 0 failed.
Every covered documentation snippet compiles against the built types.
Links are valid across 15 scan roots.
✅ Every documented component type is registered.
✅ check-control-bytes: OK (scanned 5099 tracked text file(s); skipped 85 binary).
✅ check:doc-fences — every TypeScript block in 223 document(s) is fenced ts/tsx/typescript …

check-doc-fence-languages is new on main (#6144) and arrived with the merge; it is included because the diff is 22 fenced blocks.

The resolution control line is what proves the annotations bind to the builtdist/*.d.ts; the dependency closure was rebuilt after the merge (turbo run build, __EXIT_build=0).

Root vitest from the repo root: the three doc-gate suites are Test Files 3 passed (3), Tests 157 passed (157) — the link failure that stood while this branch predated #6146 is gone. The gate that arrived with the merge passes too: check-doc-fence-languages.test.ts, Test Files 1 passed (1), Tests 20 passed (20).

Render check (taken pre-merge, on the same 22 files the merge did not touch) from served HTML, all 22 pages HTTP 200. Positive: each page renders its exported metadata type name and the link to Field Widget Props. Negative: interface AutoNumberFieldSchemainterface VectorFieldSchema — all 22 — return 0 occurrences, as do the six removed helper interfaces (interface FileMetadata, interface ColumnDefinition, interface LocationValue, interface LookupOption, interface SelectOption, interface User).

Declared narrowing on lint, as a measurement: every files: block in eslint.config.js is scoped to **/*.{ts,tsx} and no type-aware linting is configured (no projectService / project), so no untouched file's verdict can move. Running eslint over the diff's own files reports, from eslint's own config resolution, File ignored because no matching configuration was supplied for 23 of 23 files (22 .mdx + 1 changeset .md), 0 errors. CI runs the full farm regardless.

Not done here

No FRAGMENT_MARKER; UNGATED_DOCS and the ledger untouched; no type, export or union member minted; no gate weakened. Draft PR, not marked ready, auto-merge not enabled.


Generated by Claude Code

…he exported *FieldMetadata (#6138 PR 2)
Batch 2 of 2. Every `content/docs/fields` page opened with a `## Field Schema`
block that declared an interface of its own, which type-checks no matter what it
says because nothing in it refers to anything the packages export. Each of the 22
blocks left after batch 1 is now a literal annotated with that field type's
exported `*FieldMetadata`, judged by the sealed type's excess-property check, and
each page links the shared `widget-props.mdx` page batch 1 added.
Sealedness was measured, not inherited: all 26 annotated types (22 field metadata
types plus SelectOptionMetadata, GridColumnDefinition, UploadedFileMetadata and
LookupColumnDef) carry no index signature and produce TS2353 on a nonsense key,
while the same control against the components lane's BaseSchema/ButtonSchema
produces zero diagnostics.
Every divergence was checked against its renderer before being removed. Two keys
the widgets genuinely read but no exported type declares are filed rather than
deleted (#6153); the location field's undeclared value shape is filed as #6154.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019b5UBNMtTzKbVtZZGvFuxe
@yinlianghui-tw
yinlianghui-tw marked this pull request as ready for review August 24, 2026 22:00
@yinlianghui-tw
yinlianghui-tw added this pull request to the merge queueAug 24, 2026
Merged via the queue into main with commit 0752975Aug 24, 2026
22 checks passed
@yinlianghui-tw
yinlianghui-tw deleted the claude/issue-6138-fields-schema-pr2 branch August 24, 2026 22:12
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

2 participants

@yinlianghui-tw@claude