Repository navigation
finding(docs): component reference pages declare their own interface, so the doc-snippet gate can never see the props they invent — 4 measured on the 5 pages #6122 PR 2 touched alone #6143
Description
Measured by #6122 PR 2 (PR #6142) on origin/main bfdb9f906, against a freshly built packages/types/dist/*.d.ts. Filed unassigned, not fixed — the dispatch for that PR ruled "anything else is a finding — report it, do not reconcile it."
The structural hole, which is the point
The ## Schema block on a content/docs/components/** reference page does not import the type it describes. It re-declares it:
interface RadioGroupSchema {
type: 'radio-group';
...
}A self-declared interface compiles no matter what it says. So check-doc-snippet-types — even once #5867 re-fences these blocks as ts — will judge them green while every key inside is invented. The gate's own header already names this failure mode for a different case:
A gate that checks the one thing that is right converts "unverified" into a green, which is worse than no gate.
ActionConfig (#6122) was only ever visible because it was an undefined name. A key that is merely wrong produces no diagnostic at all. #6122 is therefore not the disease; it is the one symptom that happened to be detectable.
What was measured
Five pages were swept — the exact five PR #6142 corrected, chosen only because they were already open. Documented props were compared against the shipped interface body plus everything inherited from BaseSchema, so className, disabled and friends are correctly counted as real. Four divergences remain:
| page | documented | shipped type says | read by a renderer? |
|---|---|---|---|
form/radio-group.mdx |
direction?: 'vertical' | 'horizontal' |
no direction; the slot is orientation?: 'horizontal' | 'vertical' — form.d.ts:377 |
no — neither name appears in packages/components/src/renderers/form/radio-group.tsx |
form/combobox.mdx |
searchPlaceholder?: string, emptyText?: string |
neither is declared on ComboboxSchema — form.d.ts:1283 |
no — neither appears in renderers/form/combobox.tsx |
form/command.mdx |
CommandItem.shortcut?: string[] |
CommandItem declares only value, label, icon — form.d.ts:1329 |
no |
feedback/toast.mdx |
variant?: 'default' | 'destructive' |
variant?: 'default' | 'success' | 'warning' | 'error' | 'info' — feedback.d.ts:123. 'destructive' is not a member, and four real variants are undocumented |
'destructive' appears nowhere in renderers/feedback/toast.tsx |
toast.mdx additionally omits two props the type does declare: position (feedback.d.ts:133) and onDismiss (feedback.d.ts:144).
toast.mdx's variant is the worst of the four, because it is the one an author is most likely to copy: variant: 'destructive' is a plausible-looking value, it matches the Shadcn vocabulary a reader arrives with, and it is not in the union. It fails no gate today and it would fail no gate after re-fencing.
Why this is not the same card as #6122
#6122 asks which type did these props mean and is answered from the .d.ts. This asks why can a reference page say anything at all and stay green, and the answer is the self-declared interface. The two ship independently: PR #6142 corrects the ActionConfig sites without touching any of the above, and none of the above would be caught by the correction.
The class also recurs. #4653 — "the toggle-group schema block teaches type for the selection mode, but the renderer reads selectionType" — is the identical defect, found by eye and closed one page at a time. It has no mechanical guard, so it comes back.
The deciding question, ⛔ not decided here
content/docs/components pages were swept, and 4 divergences fell out of those five. The unswept remainder is unmeasured and should be measured before anything is decided.
- Sweep and fix by hand — extend the measurement to every
componentspage and correct each divergence. Honest, but it is docs(components): the toggle-group schema block teachestypefor the selection mode, but the renderer readsselectionType#4653's approach at scale, and it buys no guard against the next one. - Make the blocks import instead of re-declare — a page that writes
import type { RadioGroupSchema } from '@object-ui/types';and then annotates an authored literal is checked by the gate that already exists. Costs a rewrite of the block's shape and changes what the reader copies. - A new gate that compares a self-declared
interface Fooin docs against the shippedFooof the same name — catches the class without rewriting the pages, but has to answer what a page is allowed to omit (all four pages above legitimately show a subset).
Refs: #6122 / PR #6142 (where this was measured) · #5867 (the lane whose re-fencing will report these pages green) · #4653 (same class, closed per-page) · #4895.
Generated by Claude Code
Activity
yinlianghui-tw commentedon Aug 24, 2026
PM grading, ruling + dispatch order — R20
Graded and claimed by the
domain:devx@ objectui execution seat (#5748), PM sessionsession_019b5UBNMtTzKbVtZZGvFuxe. Branch:claude/issue-6143-components-schema-import.Ruling: option 2 — measured first
Make the blocks import instead of re-declare. Option 1 is #4653's approach at scale and the card's own evidence convicts it: #4653 was this exact defect, found by eye, closed one page at a time, and it came back — an approach with no guard buys one clean sweep and no floor.
Option 3 is rejected for the reason this seat has now applied three times (#6122 option B, #6138 option 4, here): ⛔ a checker whose job is to keep a second source of truth honest is machinery so a divergent copy can safely persist. Option 2 deletes the second source of truth; option 3 institutionalises it and then hires a guard. And option 3 has to answer "what may a page legitimately omit" — a question option 2 never has to ask, because a subset of an imported type is just a subset.
⭐ This is the same ruling, on the same class, as #6138 one lane over — the⚠️ Read #6138's thread before you design anything here — its round-1 measurement and my ruling on it are the precedent, and two lanes solving one problem two different ways is its own defect. Where you can share a shape with it, share it.
content/docs/fieldspages whoseField Schemablocks declare their own interface and compile vacuously. Same disease, same medicine, and #6138 round 2 is in flight implementing it right now.⛔ But measure before you fix — the card is right that the denominator is unknown
Only 5 of roughly 80
content/docs/componentspages were swept, and 4 divergences fell out of those 5. ⛔ Do not extrapolate that rate and do not start editing on it. Step 1 is the full sweep: everycontent/docs/componentspage, documented props compared against the shipped interface body plus everything inherited fromBaseSchema(soclassName,disabledand friends are correctly counted as real, exactly as the 5-page sweep did).Report that number before implementing. Two things it decides:
⛔ STOP AND REPORT if the sweep turns up a page shape where option 2 cannot work — a
## Schemablock describing a type that is not exported at all, for instance. That is a ruling, not an implementation detail. Round 1 of #6138 stopping on exactly this kind of finding is why the fix there is now correct instead of destructive.The four already measured — fix them, and note what else the type says
form/radio-group.mdxdirectionorientation—form.d.ts:377form/combobox.mdxsearchPlaceholder,emptyTextform/command.mdxCommandItem.shortcutCommandItemdeclares onlyvalue,label,iconfeedback/toast.mdxvariant: 'default' | 'destructive''default' | 'success' | 'warning' | 'error' | 'info'toast.mdxis the one to get right and the card says why:'destructive'is not a member, it is the Shadcn vocabulary a reader arrives with, and it is the value most likely to be copied. The page also omits four real variants plusposition(feedback.d.ts:133) andonDismiss(feedback.d.ts:144).⛔ Standing refusals
$schemamarker — the producer-side half of #5127's Option B #5329, Four fields docs pages import a cell renderer @object-ui/fields does not export — and two of them name a renderer that has no export at all #6107, finding(docs): 15 component reference pages annotate props withActionConfig, a type@object-ui/typeshas never exported — the name needs a ruling before #5867 can cover them #6122, finding(docs): twocontent/docs/fieldssnippets depend on identifiers the snippet program cannot resolve — a fabricateddbhandle and an undeclaredajv— each needs a ruling before #5867 can cover them #6126, finding(docs): #5867's population is derived fromplaintextfences only, so a TS block fencedtextis invisible to both the gate and the batch lane #6135-adjacent, finding(docs): everycontent/docs/fieldspage's "Field Schema" block declares its OWN interface, so it compiles vacuously — and the ones measured name keys the exported*FieldMetadatatypes do not have #6138). Documentation follows the code.FRAGMENT_MARKER— these are genuinely TypeScript. Declared fragments must come back unmoved, and that number is the proof.content/docs/componentsis finding(docs): TypeScript examples fenced as plaintext escape check-doc-snippet-types — 211 blocks in 122 files, and #5044 proved one of them taught a type error under a gate that reports the file as covered #5867's lane and is blocked on [Decision] Five documented action props have no declared slot at all — delete them, move them onto the item, or is this a types gap? #6132. Measure through a throwaway re-fence probe under atrap … EXIT INT TERM, never committed. This card changes what the blocks say; finding(docs): TypeScript examples fenced as plaintext escape check-doc-snippet-types — 211 blocks in 122 files, and #5044 proved one of them taught a type error under a gate that reports the file as covered #5867 changes how they are fenced.sonner,context-menu,menubar,dropdown-menu,button-group. They are with the maintainer. PR docs(components): name the shipped handler on five action props (#6122 PR 2) #6142 left them byte-identical and so must this.Verification
main, inject a wrong key into a## Schemablock and show the gate reports the page green; after your change, the same injection reddens it. Same page, same key, opposite verdicts. Mutation confirmed on disk by grep before any result is read. That single pair is the whole case for this card, and without it the PR is a rewrite with no evidence it bought anything.dist/*.d.ts— build first, quote the gate's own resolution control line.git checkout— a baregit checkout --wiped an entire uncommitted fix on this card's sibling today. Usegit checkout HEAD --followed by the path. ⛔ Nevergit stash— shared stack, other agents are using it now.os-dev-report, and write angle-bracket fragments in words.Refs: #6138 (same class, same ruling, in flight — read it first) · #6122 / PR #6142 (where this was measured) · #5867 (the lane) · #4653 (the class, closed per-page, recurred) · #6132 (what is off-limits).
Generated by Claude Code
yinlianghui-tw commentedon Aug 24, 2026
os-dev-report
STOPPED at step 1 as the dispatch order requires — option 2's mechanism is capped on this lane, and the cap is already a maintainer ruling
status: needs_decision. No PR. Branchclaude/issue-6143-components-schema-importis pushed but holds no commits beyondorigin/main(pushed empty as the write-route probe). Worktree clean.The order's stop condition fired, in a stronger form than the example it gave:
That shape exists (11 names). But the sweep found something that decides the card before those 11 matter: option 2's central claim cannot be delivered for 73 of the 87 importable names, and the reason is already filed, measured, and ruled by the maintainer as #5155.
The blocker, proved with the gate itself
BaseSchema(packages/types/dist/base.d.ts:230) ends with an index signature that is deliberate and documented:An index signature disables TypeScript's excess-property check. So annotating an authored literal against
RadioGroupSchema— option 2's exact mechanism — accepts any key.The before/after pair the order asked for, run on the real gate
I built the option-2 conversion of
form/radio-group.mdxas a throwaway probe (re-fenced tots, self-declared interface replaced byimport typeplus an annotated literal), injected the wrong key, and rancheck:doc-snippet-types. Never committed; restored under atrap ... EXIT INT TERM; mutation confirmed on disk by grep anchored on the text I meant to change, before any result was read.Leg 1 — option 2 applied, wrong KEY injected (
direction, where the shipped slot isorientation):GATE_EXIT=0. The block entered the compile population (248 to compile becomes 249; 73 pages holding a ts block becomes 74), it was judged, and it is GREEN with the wrong key sitting in it.⭐ That is the finding. Option 2 on this lane converts an uncompiled vacuous block into a compiled vacuous block. The blocks-to-compile count goes up — which is exactly the number the PM records having over-accepted #5867's batches on — while the check buys nothing for the divergence class the card is about.
Leg 2 — wiring self-check, same page, same shape, bad VALUE on a DECLARED member (
orientation: 'diagonal'):GATE_EXIT=1. So Leg 1's green is a measurement, not broken wiring — the same machinery reddens the moment the divergence is one the index signature does not wave through.Baseline, unmodified tree, for the delta:
This is #5155, and it is already ruled
#5155 is open,
pm:queue: "BaseSchema's[key: string]: anyleaves every component schema open, so a 'declare the surface' fix can never reject a misspelled TOP-LEVEL key." Maintainer ruling recorded 2026-08-19 (verbatim reply 「全部接受」): option C — enforce at the zod/publish boundary, phased, plus option D's ceiling statement immediately.This card's own PM session posted the clarification on #5155 one minute after dispatching this card, and it draws exactly the line that matters here — what a tool can READ is not capped, what a validator can REJECT is:
Option 2 is a REJECT mechanism. It is on the capped side.
The full sweep — all 76 pages, as ordered
Resolved through the gate's own
derivePackageTypePaths(), so it reads what the gate reads:Zero
src/leaks — every number below is the shipped surface.content/docs/components## Schemaheadingform/toggle.mdx, holds no block — see findings)interfacenames declared in those blocksBaseSchema's index signature)What option 2 would and would not buy, against the four already measured
feedback/toast.mdx—variant: 'destructive'TS2322, proved by compileform/command.mdx—CommandItem.shortcutTS2353: Object literal may only specify known properties, and 'shortcut' does not exist in type 'CommandItem'form/radio-group.mdx—directionform/combobox.mdx—searchPlaceholder,emptyTextExactly half. ⭐ Worth noting for the ruling: the half it does catch includes
toast.mdx, which the order called "the one to get right" —'destructive'is a value on a declared member, so it reddens.The 11 names with no importable shipped type
sidebar.mdx(SidebarItem,SidebarGroup) ·span.mdx(SpanSchema) ·filter-builder.mdx(FilterCondition) ·toggle-group.mdx(ToggleGroupItem) ·layout/page.mdx(PageSchema) ·layout/semantic.mdx(SemanticSchema) ·header-bar.mdx(Breadcrumb) ·context-menu.mdx(ContextMenuItem) ·dropdown-menu.mdx(DropdownMenuItem) ·menubar.mdx(MenubarItem)Three sub-shapes, and they do not want the same answer:
ToggleGroupItemis a reachability defect, not an absence. It is declared andexported atpackages/types/dist/disclosure.d.ts:113— butindex.d.ts:60re-exports onlyAccordionItem, ToggleGroupSchema, AccordionSchema, CollapsibleSchema, DisclosureSchemafrom that file, and the packageexportsmap has no./disclosuresubpath. So a reader cannot import it by any specifier. This is objectui#5053's lesson exactly: the name set has to come from the package's exports, not from a grep. Fixable by adding it to the re-export list — but that is minting reachability, so it is a ruling.sidebar.mdxdocuments an API that does not exist. ItsSidebarSchemadocumentsitemsandgroupswithSidebarItem/SidebarGrouphelpers; the shippedSidebarSchemadeclaresnav?: NavLink[],content,footer,position,collapsible. Not drift in a key or two — a different shape entirely.SpanSchema,PageSchema,SemanticSchema,Breadcrumb,FilterConditionresolve to nothing (TS2724: '"@object-ui/types"' has no exported member named 'SpanSchema'. Did you mean 'AnySchema'?).FilterConditionexists only inpackages/app-shell/src/.../datasetFilterCondition.js, never shipped.ContextMenuItem,DropdownMenuItemandMenubarItemland on three of #6132's five off-limits files. 11 of the 68 divergent keys land on those five pages; they were measured and left byte-identical, and nothing here proposes touching them.The renderer check — it caught two things this card would otherwise have destroyed
Every one of the 68 divergences was checked against its renderer, per the order. 13 keys are genuinely read, i.e. undeclared-but-consumed capabilities — a types defect, routed out as instructed:
content/docs/componentspages #6150 — 13 keys acrossTextSchema.content,CarouselSchema.opts/orientation/itemClassName,TreeViewSchema.nodes/onNodeClick/title,CheckboxSchema.required,FileUploadSchema.buttonText/wrapperClass,FilterBuilderSchema.wrapperClass,HoverCardSchema.align,ContextMenuSchema.trigger. Two are behavioral, not cosmetic:CheckboxSchema.requireddrives the visible required marker;TreeViewSchema.onNodeClickis invoked as a callback.StackSchema, declared as Omit-of-FlexSchema-minus-type, erases every named member — it ships declaring onlytype, because Omit collapses underBaseSchema's index signature #6151 —StackSchema.gap/.childrenlooked identical to that class and are not.StackSchema extends Omit<FlexSchema, 'type'>, andOmitover a type carrying an index signature erases every named member:FlexSchemaresolves to 25 declared properties,StackSchemato 1 (type). The docs are right and the shipped type is wrong. Correctingstack.mdxto match its type — which is what this card would have done — would have deleted three correct entries.Two further candidates were rejected on inspection rather than filed:
NavigationMenuItem.itemsandFilterField.value. The renderer readsschema.items/schema.valueoff the top-level schema, not off the nested item type the docs declare them on, so those are docs-only keys, not consumed capabilities.Two smaller findings, recorded not actioned
form/toggle.mdxhas no schema block at all — its## Schemasection reads, in full,(Schema documentation temporarily disabled). It is 1 of the 76 and would be silently skipped by any conversion.plaintext, one (form/file-upload.mdx) fences ittext, one has no block. Socheck-doc-snippet-typesreads zero of them right now. The vacuity the card describes is currently potential — it becomes actual the moment finding(docs): TypeScript examples fenced as plaintext escape check-doc-snippet-types — 211 blocks in 122 files, and #5044 proved one of them taught a type error under a gate that reports the file as covered #5867 re-fences, which is what makes ruling before that lane moves the right sequencing.Why I did not implement the sealed 14 anyway
It would be defensible to convert just the 14 sealed names and bank the 10 divergences option 2 does catch. I did not, for two reasons that are the PM's to weigh rather than mine:
CommandItem,FilterField,FilterGroup,ButtonGroupButton,NavigationMenuItem), not the*Schematypes the pages are about. A page whose top-level schema is still a hand-written interface and whose item type is imported is a third shape, and inventing it mid-card is the improvisation round 1 of finding(docs): everycontent/docs/fieldspage's "Field Schema" block declares its OWN interface, so it compiles vacuously — and the ones measured name keys the exported*FieldMetadatatypes do not have #6138 was praised for not doing.Decisions needed
See the structured block below. In short: option 2 delivers roughly half of what the card wants and cannot deliver the other half without #5155's program reaching this layer — and #5155's ruling deliberately put enforcement somewhere else.
Housekeeping
git status --shortempty;git rev-list --count origin/main..HEAD= 0..probe6143/, the re-fenced page) removed under traps;radio-group.mdxverified byte-identical to its pristine copy bydiff -q.FRAGMENT_MARKERadded, no gate weakened, no type/export/union member minted, no re-fencing committed, [Decision] Five documented action props have no declared slot at all — delete them, move them onto the item, or is this a types gap? #6132's five files untouched.Structured report
{ "issue": 6143, "status": "needs_decision", "branch": "claude/issue-6143-components-schema-import", "pr": null, "premise_still_valid": true, "summary": "Step 1's full sweep fired the order's STOP condition, so I did not implement. All 76 content/docs/components pages were swept: 98 interface names in their Schema blocks, 604 documented keys, 68 keys that are not declared members of the shipped type. The blocker is that BaseSchema ends with a deliberate, documented '[key: string]: any', so 73 of the 87 importable names are OPEN and an annotated literal accepts any key. Proved on the real gate: an option-2 conversion of radio-group.mdx carrying the wrong key 'direction' entered the compile population (248 to compile becomes 249), was judged, and reported GREEN at exit 0 - while a wiring self-check on the same page with a bad VALUE on a declared member ('orientation: diagonal') reddened with TS2322 at exit 1. So option 2 turns an uncompiled vacuous block into a COMPILED vacuous block, raising the blocks-to-compile count while catching nothing for 58 of the 68 divergences. This is #5155, open and pm:queue, which the maintainer ruled on 2026-08-19 (option C) by putting unknown-key rejection at the zod/publish boundary and NOT at the TypeScript layer - the layer option 2 relies on. Option 2 does still catch value divergences on declared members (toast.mdx variant 'destructive', the one the order called the one to get right) and key divergences on the 14 SEALED helper types (command.mdx CommandItem.shortcut), so it delivers exactly 2 of the 4 already-measured cases. The renderer check caught two things the card would otherwise have destroyed: 13 keys the renderers genuinely read that no type declares (filed #6150), and StackSchema.gap/.children, which are correct docs against a broken type because Omit over an index-signature type erases every named member, leaving StackSchema declaring 1 property where FlexSchema declares 25 (filed #6151). Also found: 11 names with no importable shipped type, of which ToggleGroupItem is a reachability defect (exported in disclosure.d.ts but re-exported by nothing and no subpath) and sidebar.mdx documents an entirely different shape from the shipped SidebarSchema.", "tests": "No code changed, so nothing to verify beyond the measurement. Build first, per discipline, under the shared verify lock: 'pnpm --filter @object-ui/types... build' VERDICT command-exit 0, then the gate's own 20-package build filter via turbo --concurrency=2, VERDICT command-exit 0 (32/32 tasks, FULL TURBO). Measurement resolves through the gate's own derivePackageTypePaths(), so it reads what the gate reads: '@object-ui/types -> /home/user/objectui-6143/packages/types/dist/index.d.ts', 47 entry files from packages/*/dist/, 0 from packages/*/src/ (zero src leaks). GATE BASELINE, unmodified tree, via os-verify-lock.sh: control lines 'resolution Module name @object-ui/types was successfully resolved to /home/user/objectui-6143/packages/types/dist/index.d.ts' and 'sentinel importing ThisNameIsDefinitelyNotExported produced 1 diagnostic(s) (TS2305)'; 'Covered blocks: 359 - 248 to compile, 111 declared fragment(s).'; 'Semantic phase: 248 of 248 block(s) judged, 0 failed.' GATE_EXIT=0. CENTRAL PAIR, both on radio-group.mdx as throwaway probes under trap EXIT INT TERM, never committed, mutation confirmed on disk by grep anchored on the changed text BEFORE any result was read (injected import occurrences 1, injected wrong key occurrences 1, removed 'interface RadioGroupSchema {' occurrences 0, fence confirmed ts). LEG 1 option-2 conversion carrying the wrong KEY 'direction': 'Covered blocks: 360 - 249 to compile, 111 declared fragment(s).' / 'Semantic phase: 249 of 249 block(s) judged, 0 failed.' / 'Every covered documentation snippet compiles against the built types.' GATE_EXIT=0 - GREEN, which is the finding. LEG 2 wiring self-check, same page and shape, bad VALUE on a declared member: '[semantic] content/docs/components/form/radio-group.mdx:41:3 TS2322: Type \"diagonal\" is not assignable to type \"horizontal\" | \"vertical\" | undefined.' / 'Semantic phase: 249 of 249 block(s) judged, 1 failed.' GATE_EXIT=1 - so Leg 1's green is a measurement, not broken wiring. Supporting compile probes through the same path derivation: RadioGroupSchema annotated literal carrying BOTH 'direction' and a nonsense key 'thisKeyIsCompleteNonsense' produced 0 diagnostics; ToastSchema variant 'destructive' produced TS2322; CommandItem from @object-ui/types/form carrying 'shortcut' produced TS2353; 'keyof RadioGroupSchema = literally-anything-at-all' produced 0 diagnostics, confirming the index signature. Renderer reads verified by eye, not only by regex: text.tsx:51,56 schema.content; checkbox.tsx:45,49 schema.required; tree-view.tsx:98,99,105,115 schema.onNodeClick/nodes/title; hover-card.tsx:24 schema.align; carousel.tsx:23,24,30; file-upload.tsx:78,123; and combobox.tsx confirmed to contain NEITHER searchPlaceholder NOR emptyText, matching the card's measurement. Restoration verified: git status --short empty, git rev-list --count origin/main..HEAD = 0, and radio-group.mdx diff -q byte-identical to its pristine copy.", "open_questions": [ { "question": "Option 2's mechanism is capped by #5155, which the maintainer already ruled by putting unknown-key rejection at the zod/publish boundary rather than the TypeScript layer. Applied to this lane it catches value divergences and the 14 sealed helper types (10 of 68 keys) and misses key divergence on the 73 open schema types (58 of 68), while RAISING the blocks-to-compile count. How should the card proceed?", "options": [ "A - Take the half that works, honestly scoped: convert every page, and state in the PR body that the conversion pins VALUES on declared members and KEYS on sealed helper types only, with key divergence on BaseSchema-derived schemas explicitly out of reach pending #5155. Buys toast.mdx (the order's stated priority) and command.mdx, plus the undefined-name class that made #6122 visible. Cost: 73 pages get a rewrite whose main advertised property does not hold for them, and the blocks-to-compile rise reads as more coverage than was bought.", "B - Sequence this card behind #5155's option-C program and hold. The strict authoring variant of the component schemas is exactly the missing rejection point; once a schema family is strict, an annotated literal in a doc block can be checked against the STRICT variant and option 2 delivers its full claim for that family. Cost: this card waits on a phased program with no date, and the pages stay vacuous meanwhile - though they are also currently uncompiled, so nothing regresses.", "C - Change the target of the annotation rather than waiting: annotate doc literals against the ZOD-inferred strict type (or a Strict<T> helper) instead of the TS interface, so the doc block is checked against the surface that will actually reject. Delivers the full claim now and aligns with the ruled enforcement layer. Cost: needs the strict variant to exist for these schemas, which is #5155's option-C work arriving through this card's back door - a scope expansion that is the maintainer's call, not mine.", "D - Fix only the four already-measured pages plus the 11 unresolvable names as ordinary docs corrections, drop the import mechanism entirely, and close the card as option 1. Cost: this is exactly #4653's approach the ruling rejected, and it buys no floor." ], "recommendation": "B, with a narrowly scoped slice of A taken now. Real business need: the reader harm is measured and concrete - toast.mdx teaches variant 'destructive', which is not a union member, is the Shadcn vocabulary a reader arrives with, and is the value most likely to be copied. That one is a VALUE on a declared member, so option 2 catches it today with no dependency on #5155. So take A's mechanism for the cases where it demonstrably works - the four measured pages plus the 14 sealed helper types - and let the 73 open schemas wait for B, rather than rewriting 73 pages around a guarantee that does not hold for them. Long-term soundness: #5155 is ruled and the ruling names the zod/publish boundary as the rejection point; building a second, weaker rejection attempt at the TS layer is the divergent-copy pattern this seat has rejected three times, just wearing the fix's clothes rather than the checker's. Making AI-written metadata hard to get wrong: this is the axis that argues hardest against a full option-2 rollout, because a compiled-and-green block is MORE trusted than an uncompiled one - Leg 1 shows the gate would actively vouch for a page containing an invented key, and raising blocks-to-compile while doing it makes the false assurance measurable in the direction of 'better'. An unchecked plaintext block at least advertises that it is unchecked. Startup scope discipline: B mints nothing and spends nothing; C smuggles #5155's phased program into a docs card; A spends 73 page rewrites for a property that holds on 14 of them.", "recommendation_note": "I did not implement the sealed-14 slice unilaterally because it creates a third page shape - imported item type beside a hand-written top-level interface - and inventing a shape mid-card is what round 1 of #6138 was right not to do." }, { "question": "11 declared names have no importable shipped type, and they are three different defects, not one. How should each be routed?", "options": [ "ToggleGroupItem is a REACHABILITY defect: declared and exported at packages/types/dist/disclosure.d.ts:113, but index.d.ts re-exports only five names from that file and the package exports map has no ./disclosure subpath, so no specifier can reach it. Adding it to the re-export list is a one-line fix but it is minting reachability, which needs a ruling.", "sidebar.mdx documents an API that does not exist: it teaches items/groups with SidebarItem/SidebarGroup helpers, where the shipped SidebarSchema declares nav/content/footer/position/collapsible. This is a page rewrite against the real shape, not a key correction - and worth checking against the renderer before anything is deleted.", "SpanSchema, PageSchema, SemanticSchema, Breadcrumb and FilterCondition resolve to nothing shipped. FilterCondition exists only inside packages/app-shell/src and is not published at all. These need per-page decisions about what the page is actually documenting." ], "recommendation": "Route them as three separate items rather than one batch, and do NOT mint any type for them. ToggleGroupItem is the only one with a mechanical answer, and even that one is a deliberate widening of the public surface, so it wants an explicit yes. sidebar.mdx should be re-measured against its renderer first - given that the same sweep found 13 undeclared-but-consumed keys elsewhere, the possibility that sidebar's renderer reads items/groups is live and would make it a types card rather than a docs card. I did not investigate it here to avoid widening scope without a ruling." }, { "question": "Does the ruling still hold now that the lane's vacuity is potential rather than actual? 74 of the 76 pages are plaintext-fenced and one is text-fenced, so check-doc-snippet-types reads ZERO of them today.", "options": [ "Treat it as urgent anyway - the vacuity becomes real the moment #5867 re-fences, and fixing the blocks first means the re-fencing lands on already-correct pages.", "Treat it as sequencing headroom - nothing is being falsely reported green right now, so there is time to let #5155's program reach the layer, and #5867 is in any case blocked on #6132." ], "recommendation": "The second, and it strengthens option B above. The card's framing - the gate reports these pages green while every key inside is invented - describes what happens AFTER #5867 re-fences; today the gate does not read them at all. That is real headroom rather than a reprieve, and it means the ordering question is whether this card or #5155's strictness work should reach the lane first. My measurement says #5155 first, because re-fencing plus option 2 without it produces the worst state of the three: compiled, judged, green, and wrong." } ], "out_of_scope_findings": [ "filed as #6150: 13 top-level schema keys that component renderers genuinely read are declared by no shipped type - TextSchema.content, CarouselSchema.opts/orientation/itemClassName, TreeViewSchema.nodes/onNodeClick/title, CheckboxSchema.required, FileUploadSchema.buttonText/wrapperClass, FilterBuilderSchema.wrapperClass, HoverCardSchema.align, ContextMenuSchema.trigger; two are behavioral rather than cosmetic", "filed as #6151: StackSchema = Omit<FlexSchema, 'type'> erases every named member, shipping an interface that declares 1 property where FlexSchema declares 25, because Omit collapses under BaseSchema's index signature - the docs are right and the type is wrong", "not filed, recorded here: form/toggle.mdx has no schema block at all, its Schema section reads only '(Schema documentation temporarily disabled)'", "not filed, recorded here: ToggleGroupItem is exported at packages/types/dist/disclosure.d.ts:113 but re-exported by nothing and has no subpath in the exports map, so it is unreachable by any specifier - raised as an open question above rather than filed, because the fix widens the public surface and needs a ruling" ] }Generated by Claude Code
Generated by Claude Code
yinlianghui-tw commentedon Aug 24, 2026
Erratum on the report above — GitHub's sanitizer ate three generic arguments
Not a change to any finding, number or recommendation. Recording it because the report is the artifact the ruling gets made from, and because the same hazard damaged one of the cards this sweep filed badly enough to invert its meaning.
What happened. GitHub's body sanitizer strips any fragment shaped like an HTML tag — an angle bracket followed by an identifier. It does this inside fenced code blocks too, which is the part worth knowing. Three spots in the report above lost text after posting:
StackSchema extends OmitStackSchema extendsOmit-of-FlexSchema-minus-typea Strict helperStrict-of-T helperout_of_scope_findings[1]in the JSONStackSchema = Omit erases every named memberStackSchema, declared as Omit-of-FlexSchema-minus-type, erases every named memberNone of the three changes a number or a conclusion — the mechanism is stated in words elsewhere in the same report ("Omit over an index-signature type erases every named member", which survived intact). The JSON parses and every other field is byte-correct.
The related repairs, both done:
StackSchema, declared as Omit-of-FlexSchema-minus-type, erases every named member — it ships declaring onlytype, because Omit collapses underBaseSchema's index signature #6151 was rewritten and retitled. Its first version was mangled to the point of inversion: the fenced declaration rendered asexport interface StackSchema extends Omit {, andPickof T overExcludeofkeyof Tminus K rendered asPick>. A reader would have read the opposite of the finding. It now spells every generic in words.content/docs/componentspages #6150 was edited to restore two smaller losses (aschema.placeholder and the same Omit clause). Its 13-row table was undamaged.Omit<...>survive; a literal generic argument does not. Read every body back after posting; I caught these only because I did.Generated by Claude Code
Generated by Claude Code
yinlianghui-tw commentedon Aug 24, 2026
PM re-ruling — ⛔ my option-2 ruling was WRONG for this lane, and the measurement is what proves it
Ruled by the
domain:devx@ objectui execution seat (#5748), PM sessionsession_019b5UBNMtTzKbVtZZGvFuxe.Owning the error plainly
I ruled option 2 on the reasoning that "annotating against the sealed type makes the page structurally incapable of teaching a key the type lacks, because the excess-property check enforces it rather than a reviewer." ⛔ That premise is false here.
BaseSchemaends with a deliberate, documented[key: string]: any, so 73 of the 87 importable names are OPEN and an annotated literal accepts any key at all.I asserted "sealed" without measuring it. The order I wrote even told you to measure everything else first — and the one thing I did not put on that list is the one thing the whole ruling rested on.
⭐ And you did not merely contradict me, you proved it on the real gate with its own counter-control. An option-2 conversion of
radio-group.mdxcarrying the wrong keydirectionentered the compile population (248 → 249 blocks), was judged, and reported GREEN at exit 0; the same page with a bad value on a declared member reddened withTS2322at exit 1. That second leg is what makes the first a reading instead of broken wiring.keyof RadioGroupSchema = literally-anything-at-allproducing zero diagnostics puts it beyond argument.⭐ The conclusion that reverses the ruling
Option 2 here turns an uncompiled vacuous block into a COMPILED vacuous block — catching nothing for 58 of the 68 divergences while raising blocks-to-compile.
That is not neutral, it is negative. Your framing is the correct one and I am adopting it as this seat's standing rule: ⭐ a compiled-and-green block is more trusted than an uncompiled one, and an unchecked plaintext block at least advertises that it is unchecked. A rollout that moves the coverage number up while moving the actual assurance down is the #5044 class arriving through the fix.
The ruling
Option B — sequence the mechanism behind #5155's strict-variant program. It mints nothing, spends nothing, and nothing regresses: these pages are
plaintext-fenced today, so the gate reads zero of them. Your third question answers itself and I agree with your reading — that is genuine headroom, not a reprieve, and it means the ordering question is which reaches this lane first. ⭐ #5155 first, because re-fencing plus option 2 without it produces the worst of the three states: compiled, judged, green, and wrong.⛔ Option C is rejected for the reason you gave: annotating against a zod-inferred strict variant delivers the full claim but smuggles #5155's phased program in through a docs card. That is the maintainer's call, not this seat's.
⛔ Option A's full rollout is rejected — 73 page rewrites around a guarantee that holds for 14 of them, with the false assurance made measurable in the direction of "better."
⛔ Option D remains rejected (it is #4653 at scale, no floor).
What to take now —⚠️ narrower than the slice you offered
Fix the four measured divergences as ordinary docs corrections, with ⛔ no import, no annotation, and no change to the block shape:
feedback/toast.mdxvariant→ the shipped union'default' | 'success' | 'warning' | 'error' | 'info'; ⛔'destructive'is not a memberform/radio-group.mdxdirection→orientationform/combobox.mdxsearchPlaceholder,emptyText— declared nowhere, read by nothingform/command.mdxCommandItem.shortcut—CommandItemdeclares onlyvalue,label,icontoast.mdxis still the one to get right, for the reason the card gives:'destructive'is the Shadcn vocabulary a reader arrives with and the value most likely to be copied. It needs fixing whether or not any gate ever reads it.⛔ Blocks-to-compile must not move. Nothing is re-fenced, nothing is annotated. If that number changes, something is wrong.
The 11 unresolvable names — routed as three items, as you recommend
ToggleGroupItem— a reachability defect (exported atdisclosure.d.ts:113, re-exported by nothing, no./disclosuresubpath). ⛔ Not taken here: a one-line re-export is still a deliberate widening of the public surface and wants an explicit yes.sidebar.mdx— documents an entirely different shape from the shippedSidebarSchema. ⛔ Not taken here.items/groupsis live, and that would make it a types card. It gets measured against its renderer before a word is deleted.SpanSchema,PageSchema,SemanticSchema,Breadcrumb,FilterCondition— per-page questions.FilterConditionlives only inpackages/app-shell/srcand is not published at all.⛔ Do not mint a type, an export, or a subpath for any of them. Eighth refusal this session.
The two filed cards are the better yield
content/docs/componentspages #6150 — 13 top-level keys renderers genuinely read that no shipped type declares, two of them behavioural. ⭐ This is exactly why the order made the renderer check mandatory: without it, option 2 would have deleted working documentation of working features.StackSchema, declared as Omit-of-FlexSchema-minus-type, erases every named member — it ships declaring onlytype, because Omit collapses underBaseSchema's index signature #6151 —StackSchemadeclared asOmitofFlexSchemaerases every named member underBaseSchema's index signature, shipping an interface declaring 1 property whereFlexSchemadeclares 25. ⭐ The docs are right and the type is wrong — the exact inversion this card was assuming could not happen.Also noted, not filed:
form/toggle.mdxhas no schema block at all — "(Schema documentation temporarily disabled)".⭐ Adopted as a standing rule for every seat
Your process finding is more useful than it looks: GitHub's sanitizer strips angle-bracket generics inside issue TITLES and inside FENCED CODE BLOCKS, not only in prose — it inverted #6151's meaning before you caught it on read-back. This seat already required angle-bracket fragments in words; it now requires reading the body back after posting, because the mangling is silent and can reverse a claim.
Dispatch — round 2, small and bounded
The four docs corrections above, nothing else. Details in the order below.
Refs: #5155 (ruled 2026-08-19, option C — the layer this card cannot use) · #6150 / #6151 (this sweep's real yield) · #6138 (the fields twin, where the base type is sealed — the difference is measured, not assumed) · #5867 / #6132 (the lane and its other blocker) · #4653.
Generated by Claude Code
yinlianghui-tw commentedon Aug 24, 2026
os-dev-report
Round 2 done — option B implemented as exactly four docs corrections
status: done. Draft PR #6161, branchclaude/issue-6143-components-schema-importatcc607b380.Part of #6143, so the card stays open for the option-B sequencing behind #5155.origin/mainand still pointed at the pre-#6142 tree, so editing from there would have silently reverted its fiveActionConfigcorrections. I fast-forwarded to228909995first and re-recordedBASE. The diff sits on top of #6142, not across it.The four corrections
Built
packages/typesfresh first. Each value checked against the shipped.d.tsand against the zod schema — #5155 ruled the zod/publish boundary to be the enforcement layer, so I checked the layer that actually rejects, not only the one that documents. Both layers agree on all four.feedback/toast.mdxvariant?: 'default' | 'destructive'variant?: 'default' | 'success' | 'warning' | 'error' | 'info'feedback.d.ts:123feedback.zod.js:59form/radio-group.mdxdirectionorientation?: 'horizontal' | 'vertical'form.d.ts:377form.zod.js:263form/combobox.mdxsearchPlaceholder,emptyTextform.d.ts:1283form.zod.js:378form/command.mdxCommandItem.shortcutform.d.ts:1329form.zod.js:76A precision worth recording, because it is the kind of thing a batch edit gets wrong:
emptyTextis removed fromComboboxSchemaonly.CommandSchemagenuinely declares it (form.d.ts:1368,form.zod.js:406), socommand.mdxkeeps itsemptyText. The order's wording was already exact on this; the measurement confirms it.Renderer re-checked before each removal:
renderers/form/combobox.tsxcontains neither name,renderers/form/command.tsxcontains noshortcut,renderers/feedback/toast.tsxcontains no'destructive'.toast.mdx's omissions (position,onDismiss) are left as they are, deliberately — round 2 was dispatched as exactly four corrections, and a reference page may show a subset.⭐ Blocks-to-compile did not move
The ordered proof.
pnpm check:doc-snippets, before and after, same freshly built types:Nothing re-fenced, nothing annotated, nothing imported, no block changed shape — the blocks stay
plaintextand stay outside the compile population, exactly as ruled. Same resolution control line on both runs:Gates — all at
cc607b380, each quoting its own verdict lineExit captured before any pipe, every time.
check:doc-snippetsEvery covered documentation snippet compiles against the built types.check:doc-typesEvery documented component type is registered.check:control-bytescheck-control-bytes: OK (scanned 5092 tracked text file(s); skipped 85 binary).check-changeset-presenceNo source of a released package changed in this range, so no changeset is owed.check-changeset-fixedAll workspace packages are in the changeset fixed group.check-changeset-no-majorNo changeset declares a major bump.check-doc-linksLinks are valid across 15 scan roots.Lint — narrowed, with the narrowing proved rather than asserted. ESLint's own flat config admits only
**/*.{ts,tsx}plus one named.ts; no block admits.mdor.mdx. Read from ESLint itself:--format jsonover all five changed files returns 5 results, eachFile ignored because no matching configuration was supplied, 0 linted. Invariance is trivial here — no type-aware linting is configured, and the diff contains no.ts/.tsxat all, so no untouched file's verdict can move.Vitest: the diff implicates no suite, verified. Nothing references the four pages; the three files matching
content/docs/componentsnamespan.mdxanddiv.mdxin prose comments. Root-only discipline (#3378) never came up because there was no suite to run.Render-check from the prerendered HTML.
next buildofapps/site,VERDICT command-exit 0, then.next/server/app/docs/components/feedback/toast.html:The only
destructivestrings left on that page are Tailwind classes on a rendered button — where it genuinely is a member ofButtonSchema.variant— and a fixture id.@object-ui/plugin-ganttand@object-ui/plugin-mapbuilt; they were linked in the worktree but had never been built there, so the firstnext builddied onModule not found. Pre-existing worktree gap, unrelated to a diff that touches no TypeScript. Recording it because the next agent to render-check this repo will hit it.⭐ Two findings filed — and one of them says the job is half done
finding(examples): the live SchemaExample fixtures on four component pages teach the same invented keys the prose blocks just stopped teaching #6157 — the live⚠️ This may be the worse half: a reader copies a working demo more readily than an interface block, and the demo is what renders. Not fixed here — editing a fixture changes what a demo renders, not what a page says, and round 2 was bounded to four prose corrections. One precision recorded there so nobody batch-edits it wrong: the top-level
SchemaExamplefixtures on these same four pages still carry the invented keys the prose just stopped teaching:variant: "destructive"in two toast action payloads,shortcuton threeCommandItementries, anddirectionin both radio-group layout fixtures."variant": "destructive"in those same two files is a legitimate button variant (form.d.ts:30), so a blanket replace would break two working buttons.finding(components): RadioGroupSchema.orientation is declared by the type and the zod schema but read by nothing — the docs page's two Layout Options demos render byte-identical markup #6158 —
RadioGroupSchema.orientation, the very key I corrected the page to, is declared by the type and the zod schema and read by nothing. Measured from the prerendered HTML rather than by eye: all eight radiogroup roots on the page render byte-identical markup (class="grid gap-2", nodata-orientationanywhere), so the two demos under## Layout Optionsare indistinguishable and the horizontal one renders vertically. The mirror image of finding(types): 13 top-level schema keys that component renderers genuinely READ are declared by no shipped type — measured across all 76content/docs/componentspages #6150 — there the renderer reads what no type declares; here the type declares what no renderer reads. The registry metainputsforradio-groupomit it too, which makes it a clean instance of A component type has THREE declared surfaces that disagree (TS schema type / registry meta inputs / renderer prop reads), and nothing reconciles or enforces them #4631's three-disagreeing-surfaces.Both filed unassigned, both searched for duplicates first, both read back after posting.
Sanitizer discipline, per the new standing rule
Every body posted this round was read back. The PR body, #6157 and #6158 all survived intact — quotes came back as HTML entities, no text lost. I used no angle-bracket fragments anywhere, including in titles and fenced blocks.
Housekeeping
.changeset/6143-components-schema-corrections.md). ⛔ Noskip-changesetlabel was created or applied — that mechanism does not exist in this repo and minting it would fake one.ToggleGroupItem,sidebar.mdx,SpanSchema,PageSchema,SemanticSchema,Breadcrumb,FilterConditionall untouched. [Decision] Five documented action props have no declared slot at all — delete them, move them onto the item, or is this a types gap? #6132's five files byte-identical. finding(types): 13 top-level schema keys that component renderers genuinely READ are declared by no shipped type — measured across all 76content/docs/componentspages #6150/finding(types):StackSchema, declared as Omit-of-FlexSchema-minus-type, erases every named member — it ships declaring onlytype, because Omit collapses underBaseSchema's index signature #6151 untouched.git stashat any point. The fix was committed before the site build and every measurement that followed.node_modulesremoved,git worktree removesucceeded without--force.Structured report
{ "issue": 6143, "status": "done", "branch": "claude/issue-6143-components-schema-import", "pr": "https://github.com/objectstack-ai/objectui/pull/6161", "premise_still_valid": true, "summary": "Implemented the re-ruled option B as exactly four docs corrections, with no import, no annotation and no change to block shape. toast.mdx variant now reads the shipped union 'default' | 'success' | 'warning' | 'error' | 'info' ('destructive' is not a member); radio-group.mdx direction becomes orientation; combobox.mdx drops searchPlaceholder and emptyText; command.mdx drops CommandItem.shortcut. Each value was checked against a freshly built packages/types/dist/*.d.ts AND against the zod schemas, since #5155 ruled the zod/publish boundary to be the enforcement layer - both layers agree on all four. One precision the measurement confirmed: emptyText is removed from ComboboxSchema only, because CommandSchema genuinely declares it (form.d.ts:1368, form.zod.js:406), so command.mdx keeps its own. Renderers were re-checked before every removal and none of the four keys is read. Blocks-to-compile did NOT move: 248 before and after, with covered/ungated 178/44, 73 documents holding a ts or tsx block, 359 covered blocks and 111 declared fragments all identical. IMPORTANT SEQUENCING NOTE: PR #6142 landed on exactly these four files while round 1 was reporting, and my branch was one commit behind origin/main - editing from there would have silently reverted its five ActionConfig corrections, so I fast-forwarded to 228909995 and re-recorded BASE before touching anything. Two findings were filed rather than fixed: #6157, because the live SchemaExample fixtures on these same pages still carry the same invented keys the prose just stopped teaching, and #6158, because RadioGroupSchema.orientation - the key I corrected the page TO - is declared by the type and the zod schema but read by no renderer, which the prerendered HTML proves by rendering all eight radiogroups on the page byte-identically.", "tests": "All gates at the final commit cc607b380; exit captured before any pipe every time; builds under the shared verify lock. BUILD: 'pnpm --filter @object-ui/types build' VERDICT command-exit 0 (stale dist lies in both directions, so this ran before any judgement). GATE BEFORE/AFTER, the ordered proof that blocks-to-compile did not move - identical on both runs: 'Scanned 222 document(s): 178 covered (73 of them hold a ts/tsx block), 44 ungated'; 'Covered blocks: 359 - 248 to compile, 111 declared fragment(s).'; 'Semantic phase: 248 of 248 block(s) judged, 0 failed.'; 'Every covered documentation snippet compiles against the built types.' COMMAND_EXIT=0 both times, with the same control lines: resolution to /home/user/objectui-6143/packages/types/dist/index.d.ts, sentinel TS2305 producing 1 diagnostic, positive ComponentSchema producing 0. OTHER GATES, each quoting its own verdict line: check:doc-types EXIT=0 'Every documented component type is registered.' (183 docs, 1054 blocks, 887 type literals); check:control-bytes EXIT=0 'check-control-bytes: OK (scanned 5092 tracked text file(s); skipped 85 binary).'; check-changeset-presence EXIT=0 'No source of a released package changed in this range, so no changeset is owed.'; check-changeset-fixed EXIT=0 'All workspace packages are in the changeset fixed group.'; check-changeset-no-major EXIT=0 'No changeset declares a major bump.'; check-doc-links EXIT=0 'Links are valid across 15 scan roots.' LINT, narrowed with the narrowing proved from eslint's own configuration rather than asserted: every files block in eslint.config.js is ts/tsx only, and 'eslint --no-inline-config --format json' over all five changed files returns 5 results each reading 'File ignored because no matching configuration was supplied', 0 errors and 0 files linted; invariance for untouched files is trivial because no type-aware linting is configured (no projectService, no project) and the diff contains no .ts or .tsx. VITEST: the diff implicates no suite, verified not assumed - no test references any of the four pages, and the three files matching 'content/docs/components' name span.mdx and div.mdx in prose comments; the only other references to these filenames are in gitignored apps/site/.source codegen. RENDER-CHECK from prerendered HTML: 'pnpm --filter @object-ui/site build' VERDICT command-exit 0 after building plugin-gantt and plugin-map, which were linked but never built in this worktree and made the first attempt die on 'Module not found' (pre-existing, unrelated to a diff touching no TypeScript); .next/server/app/docs/components/feedback/toast.html renders the corrected line as \"variant?: 'default' | 'success' | 'warning' | 'error' | 'info';\", and the only surviving 'destructive' strings are Tailwind classes on a rendered button (a legitimate ButtonSchema.variant member) plus a fixture id. The same prerendered output is what proves #6158: all eight radiogroup roots on radio-group.html are identical, 'role=radiogroup aria-required=false dir=ltr class=\"grid gap-2\" data-obj-type=radio-group', with no data-orientation attribute anywhere and no direction attribute on the page. EDIT CONFIRMATION on disk before any result was read, anchored on the exact text intended to change, both directions: removed text counts all 0 (toast 'default' | 'destructive', radio 'direction?:', combobox searchPlaceholder and emptyText), injected text counts 1 each (toast shipped union, radio orientation), and command.mdx's shortcut count went 2 to 1, the survivor being the demo id on line 44 rather than a declared key. Control-byte scan clean on all edited files and the changeset.", "open_questions": [], "out_of_scope_findings": [ "filed as #6157: the live SchemaExample fixtures on the same four pages still carry the invented keys the prose just stopped teaching - variant 'destructive' inside the toast action payload of destructive.json and error-toast.json, shortcut on three CommandItem entries in command-palette-with-shortcuts.json, and direction in both radio-group layout fixtures; recorded there that the top-level button variant 'destructive' in those same toast files is legitimate, so a blanket replace would break two working buttons", "filed as #6158: RadioGroupSchema.orientation is declared by form.d.ts:377 and form.zod.js:263 but read by no renderer, so the page's two Layout Options demos render byte-identical markup and the horizontal one renders vertically - the mirror image of #6150, and a clean instance of #4631's three-disagreeing-surfaces since the registry meta inputs omit it too", "not filed, recorded: @object-ui/plugin-gantt and @object-ui/plugin-map were linked but never built in this worktree, so a first 'next build' of apps/site dies on Module not found until they are built - an environment gap the next agent render-checking this repo will hit" ] }Generated by Claude Code
Generated by Claude Code
yinlianghui-tw commentedon Aug 24, 2026
PM review of round 2 — ACCEPT, PR #6161 pending CI
Reviewed by the
domain:devx@ objectui execution seat (#5748), PM sessionsession_019b5UBNMtTzKbVtZZGvFuxe.Option B implemented as exactly four docs corrections, no import, no annotation, no change to block shape. ⭐ Blocks-to-compile did not move: 248 before and after, with covered/ungated
178/44, 73 documents holding a ts/tsx block, 359 covered blocks and 111 declared fragments all identical. That was the constraint I said would be the tell if something had gone wrong, and it is clean.Both enforcement layers were checked, not just one — the built
.d.tsand the zod schemas — which is the right instinct now that #5155 has named the zod/publish boundary as the layer that actually rejects.⭐ The near-miss you caught is the most valuable thing in this report
The scoping precision I got wrong and you got right
My order said "
combobox.mdx— removesearchPlaceholder,emptyText." You removedemptyTextfromComboboxSchemaonly, becauseCommandSchemagenuinely declares it (form.d.ts:1368,form.zod.js:406), socommand.mdxcorrectly keeps its own. A blanket application of my instruction would have deleted a real, declared key. Checking per-page rather than per-key is the difference.RadioGroupSchema.orientationis declared byform.d.ts:377andform.zod.js:263and is read by no renderer — proved by all eight radiogroups on the page rendering byte-identical markup, nodata-orientationanywhere, with the "horizontal" demo rendering vertically.So
direction→orientationis still the right correction — documentation follows the shipped type, anddirectionwas declared by nothing at all — but the page now documents a declared-but-inert key, and my order did not anticipate that a correction could land in that state. ⭐ You filed it as the mirror image of #6150 and as a clean instance of #4631's three-disagreeing-surfaces, which is exactly the right framing: this is not a docs defect, it is a third surface disagreeing.That is the eleventh correction to one of my orders today, and the subtlest.
#6157 is a gap in my ruling, not in your work
The prose stopped teaching the invented keys; the live
SchemaExamplefixtures on the same four pages still carry them —variant: 'destructive'inside the toast action payloads,shortcuton threeCommandItementries,directionin both radio-group layout fixtures. So the page still demonstrates what it no longer documents.buttonvariant'destructive'in those same toast files is legitimate is the detail that stops the obvious blanket replace from breaking two working buttons.Recorded, not filed
@object-ui/plugin-ganttand@object-ui/plugin-maplinked-but-unbuilt, so a firstnext buildofapps/sitedies onModule not found. That is the fifth independent sighting today. Five agents rediscovering one environment property is itself the signal, and this seat is now tracking it rather than letting each dev pay for it again.Part of #6143is correct — the card stays open for the option-B sequencing behind #5155.Generated by Claude Code
fix(examples): correct the invented keys the live SchemaExample fixtu…
fix(types): StackSchema ships its declared members instead of collaps…
os-project-manager commentedon Aug 30, 2026
H8 配对写入:
pm:dispatched→pm:blockedBlocked-by: #5155
交付 PR #6161 已于 2026-08-24T21:59:50Z 合并,本卡仍挂
pm:dispatched,已挂 5.7 天。按 PM review(
5401805349)末句定级,原文:⇒ 剩余物压在 #5155(zod/publish 边界的拒绝点裁决)上,故
pm:blocked。已交付的四处文档更正不受影响(blocks-to-compile 248 前后不动)。本笔是维护者指令下的 H8 清账(2026-08-30,session
session_014kugUSM5M5fJBsk1f8KdtN):⛔ 未改卡面范围、未动 assignee。Generated by Claude Code
fix(examples): correct the invented keys the live SchemaExample fixtu…
fix(types): StackSchema ships its declared members instead of collaps…
objectstack-fleet commentedon Sep 25, 2026
Closed
not_planned(absorbed): the remainder is objectui#5250's open half · 2026-09-25T02:10ZActing on the maintainer's instruction. Provenance: who — the maintainer; verbatim — 「D 组:真的需要你拍板(2 张) 给我具体解释,其他同意。」, approving this session's per-card proposal for this card; where — the maintainer's chat with session
session_013RWUA7bNq5bRhehLPqXwMg, 2026-09-25.[key: string]: anyleaves every component schema open, so a "declare the surface" fix can never reject a misspelled TOP-LEVEL key #5155, which closed on 2026-09-24 as a duplicate of objectui#5250. finding: JSON doc snippets are checked by nothing — the ts/tsx gate cannot see them, andBaseSchema.passthrough()makesobjectui validateaccept arbitrary undeclared keys #5250's ruling: each node schema gets a derived strict variant, andobjectui validateplus the doc-snippet gates run it. The strict face has landed (packages/types/src/strict-authoring-face.ts). What this card's doc-snippet blind spot needs is wiring that face into the doc gates, and that is finding: JSON doc snippets are checked by nothing — the ts/tsx gate cannot see them, andBaseSchema.passthrough()makesobjectui validateaccept arbitrary undeclared keys #5250's open half (pm:queue,domain:devx).BaseSchema.passthrough()makesobjectui validateaccept arbitrary undeclared keys #5250.yinlianghui-tw(last act on this card 2026-08-30). Release: sessionsession_013RWUA7bNq5bRhehLPqXwMg; cause: remainder absorbed; destination: closed.pm:blockedremoved;domain:devxanddocumentationstay.Generated by Claude Code
docs: re-fence the plugins and core remainder of objectui#5867 as ts,…
docs: re-fence the basic, data-display, feedback and form remainder o…
docs: re-fence the complex, disclosure, layout, navigation and overla…