Repository navigation
fix(examples,docs): correct the toast demos to spellings the engine executes - #6498
Conversation
…xecutes
The seven `components-feedback-toast/*` and seven `components-feedback-sonner/*`
`SchemaExample` fixtures hung an action object off `onClick`:
{ "type": "button", "label": "Destructive Toast", "variant": "destructive",
"onClick": { "action": "toast", "variant": "error", "title": "Error", … } }
`ButtonSchema.onClick` is `z.function()`, so all fourteen were a RED
`safeParse` on the ENVELOPE — measured before the change, `{"code":
"invalid_type","expected":"function","path":["onClick"],"message":"Invalid
input: expected function, received object"}` on 14 of 14. And nothing read a
handler key as an action object: `ActionRunner`'s runnable vocabulary is
`script | url | modal | flow | api | form | navigation`, with no `toast` and no
`sonner`. The docs page prints `JSON.stringify(schema)` beside each demo, so
that shape was the copy-paste surface for every reader.
It was worse than inert. `onClick` is a member of `SDUI_DOM_PASS_THROUGH_KEYS`,
so the action object reached the rendered button's DOM listener slot, and React
refuses it on click: "Expected `onClick` listener to be a function, instead got
a value of `object` type."
All fourteen now author the registered spellings the engine already executes —
`type: 'toast'` and `type: 'sonner'` — whose renderers draw their own trigger
button and call sonner's `toast()` from it. Keys are limited to those the
governing schema declares AND the renderer reads; `buttonLabel` /
`buttonVariant` are used on `sonner` (SonnerSchema declares both) and not on
`toast` (ToastSchema declares neither, though its renderer reads them).
`feedback/toast.mdx` and `feedback/sonner.mdx` follow, including two keys
sonner's page taught that neither `SonnerSchema` declares nor its renderer
reads (`duration`, `action`).
Not done here, both left to the maintainer: declaring an action union on
`ButtonSchema.onClick` with a dispatcher behind it, and giving the toast
renderers the in-toast action button and promise form the removed demos
implied. Both are capability expansions with zero runtime today.
Part of #6250
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011SfZeFWrhGLHmfq61xbz4q
|
PM review: ACCEPT. Verified from the tree at 076ed3b, not from the report. The fence held. 22 files, zero under Every row the rewritten sonner Schema block teaches is declared, and both removed rows are declared by nothing. Checked against both faces of the type rather than one:
The new toast page prose is true. "ToastSchema declares exactly five members" — the zod enum is Leaving the toast page's Schema block alone is principled, not convenient — this is the part I checked hardest, because at a glance it looks like the same defect the sonner block just had. It is not. The corrected spelling executes. The sonner renderer draws its own single Button and calls The census move is complete, and the instrument is the right one. The #6157 pin was repointed, not deleted. Measured RED first, then replaced, carrying that card's actual fact — the toast variant value is a declared member, Both open questions, answered.
One thing to carry forward, not a blocker. The counter-probe pins React's exact wording. That couples this example package's suite to a foreign dependency's message text, so a React bump can turn it red on an unrelated PR. It is the secondary assertion — "no toast was added, whatever the click did" is load-bearing and independent of it — and the comment says out loud that it is meant to turn red for review. Fine as authored. Worth remembering as the first suspect if this file ever goes red without the catalog changing. Landing state: FAILED=none on 076ed3b; four test shards, Lint and Type Check still in progress. Queued the moment those settle green. Generated by Claude Code |
…BY NAME (objectui#6124)
The zod mirrors declared 58 `on*` keys (26 distinct) across eight files as
`z.function()` — a declaration no JSON document can satisfy on a JSON-authored
vocabulary. A JSON author who wrote `onClick: { "action": "toast" }` got zod's
bare `invalid_type … expected function`, naming the key and nothing else.
Ruled shape (maintainer 2026-08-30, batch #8: Q1→A, Q2→A+C, Q3→A, Q4→B):
every site keeps its declaration and becomes a NAMED refusal arm in the #5099
`z.custom` + guidance shape (`handlerKeyRefusal()` in `zod/tombstone.zod.ts`):
the message names the key, says why JSON cannot author it, and points at the
node-type spelling PR #6498 established. The same string is the `.describe()`.
Deletion was measured and refused: under `BaseSchema.passthrough()` an
undeclared key is KEPT, and `onClick` rides `SDUI_DOM_PASS_THROUGH_KEYS` into
the DOM listener slot where React throws at click.
Accept-set change (Clause ②): a live function is refused on the mirror too.
Measured on this tree, the only runtime `safeParse` doors into these mirrors
are the CLI validators and `validateSchema` / `safeValidateSchema`;
`SchemaRenderer` validates through `@object-ui/core`'s structural validator.
TypeScript face, measured per key: `SchemaRenderer` spreads every non-metadata
schema key as a React prop, so 36 keys whose function value reaches a renderer
(read off `schema.*`, called as `props.onX`, or spread onto a Radix root / DOM
listener slot) keep their function type; 22 keys nothing reads carry the
`?: never` tombstone (ADR-0049). The parity ledger records the 35 registered
runtime-slot keys as deliberate drift (28 pairs; `MenuItemSchema` is a lazy
union outside the registry).
Out of scope per the ruling: `cell` / `custom` / `validate` /
`renderCellEditor` stay `z.function()`; `EventHandlersSchema` is objectui#6910.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NRRumy89BYdW9ogbcdHTho
…BY NAME (objectui#6124) (objectstack-ai#7339) The zod mirrors declared 58 `on*` keys (26 distinct) across eight files as `z.function()` — a declaration no JSON document can satisfy on a JSON-authored vocabulary. A JSON author who wrote `onClick: { "action": "toast" }` got zod's bare `invalid_type … expected function`, naming the key and nothing else. Ruled shape (maintainer 2026-08-30, batch objectstack-ai#8: Q1→A, Q2→A+C, Q3→A, Q4→B): every site keeps its declaration and becomes a NAMED refusal arm in the objectstack-ai#5099 `z.custom` + guidance shape (`handlerKeyRefusal()` in `zod/tombstone.zod.ts`): the message names the key, says why JSON cannot author it, and points at the node-type spelling PR objectstack-ai#6498 established. The same string is the `.describe()`. Deletion was measured and refused: under `BaseSchema.passthrough()` an undeclared key is KEPT, and `onClick` rides `SDUI_DOM_PASS_THROUGH_KEYS` into the DOM listener slot where React throws at click. Accept-set change (Clause ②): a live function is refused on the mirror too. Measured on this tree, the only runtime `safeParse` doors into these mirrors are the CLI validators and `validateSchema` / `safeValidateSchema`; `SchemaRenderer` validates through `@object-ui/core`'s structural validator. TypeScript face, measured per key: `SchemaRenderer` spreads every non-metadata schema key as a React prop, so 36 keys whose function value reaches a renderer (read off `schema.*`, called as `props.onX`, or spread onto a Radix root / DOM listener slot) keep their function type; 22 keys nothing reads carry the `?: never` tombstone (ADR-0049). The parity ledger records the 35 registered runtime-slot keys as deliberate drift (28 pairs; `MenuItemSchema` is a lazy union outside the registry). Out of scope per the ruling: `cell` / `custom` / `validate` / `renderCellEditor` stay `z.function()`; `EventHandlersSchema` is objectui#6910. Claude-Session: https://claude.ai/code/session_01NRRumy89BYdW9ogbcdHTho Co-authored-by: Claude <noreply@anthropic.com>
…049 enforce-or-remove) (objectstack-ai#9552) Fixes objectstack-ai#6910 Retires the published export `EventHandlersSchema` (`z.record(z.string(), z.function())`) from `@object-ui/types` under ADR-0049 enforce-or-remove, per the maintainer ruling recorded on the card (decision batch objectstack-ai#25, reconfirming batch objectstack-ai#8 on objectui#6124). This is a **resume**. The branch already carried a WIP commit that deleted the export and the barrel line and left a NOTE in place; that commit was deliberately incomplete and red by construction. This PR merges `origin/main` into the branch (merge, never rebase), then finishes the remaining halves. ## What landed | # | File | Change | |:--|:--|:--| | 1 | zod base module | export + declaration already gone on the WIP; NOTE **corrected twice**, see below | | 2 | zod barrel | re-export line already gone on the WIP; verified | | 3 | `zod-mirror-parity.test.ts` | the self-contained two-line `EXCLUSIONS` entry for the removed const, deleted | | 4 | `handler-keys-json-refusal-6124.test.ts` | the `MIRROR_FILES` docblock sentence the removal falsifies, rewritten | | 5 | `.changeset/6910-retire-event-handlers-schema.md` | one changeset | ## The expected red, and its resolution Removing the export turns the stale-entry census in `zod-mirror-parity.test.ts` red with exactly `['base.zod.ts#EventHandlersSchema']` — that census reads exported consts off disk, so it fires for any route that removes the export. Edit 3 is what clears it. The whole package runs **190 files / 4515 tests, all passing**, with `type-check` green across all three `tsc` passes. The deleted row's reason string is shared verbatim with the sibling `HTMLAttributesSchema` entry, so the deletion was anchored on the key line, not on the reason text; the sibling entry is untouched and still present. ## Round 2 — contract review F1 (MAJOR), repaired The review reproduced 8 of 8 claims and added two checks of its own that strengthen this PR: a set difference over all 489 `EXCLUSIONS` keys (exactly one key removed, the sibling surviving at the identical address on both refs), and a red-first proof that re-adding the retired row turns the census red naming only that key — so the delete was mandatory, not a test weakened to go green. It also found that my rewritten NOTE had shipped a **born-false census sentence**: *"every authored `events` in the corpus is `TimelineSchema.events`, an unrelated array."* **The instrument behind that claim was itself the defect.** I had matched only the JSON-quoted `"events":` spelling, which structurally cannot see a TypeScript object literal, and then generalised the result to "the corpus". Re-measured on this branch over the tracked files under `packages/`, `apps/` and `examples/`, with a live control that fires and a clean absent-token control at zero, the object-literal form finds the node-level record shape the paragraph warns about — on nodes that are not timelines — plus a larger set of hook and validation string arrays. Of the files declaring a `type: 'timeline'` node, the only ones carrying an `events` key are the declaration itself and a refusal probe. **`TimelineSchema.events` is authored zero times.** The sentence was wrong in both directions. This was the defect the rewrite existed to remove, recurring inside its own fix, and it reached the emitted `.d.ts`. **No replacement count is written.** The paragraph now states the mechanism, which does not rot — nothing declares the key, nothing reads it, so whatever a document writes there no renderer runs it — points at objectui#9553 for the census, and records that it shipped a frozen census answer once already. The operative instruction is unchanged: `.passthrough()` ⇒ kept, judged by nothing, run by nothing, do not send an author there. ## Deviation from the WIP commit, stated rather than folded in The WIP NOTE told the reader that handlers are authored as `BaseSchema.events`. **That is false on this tree**, and it is the one thing in the inherited work that was not adopted as-is: `BaseSchemaCore` has 21 members and declares no `events`; the TypeScript `BaseSchema` interface declares none either; `schema.events` and `props.events` have **0** read sites across `packages`, `apps` and `examples`, against live controls `schema.className` and `schema.visible` firing in the same pass; and `@objectstack/spec` 17.4.0 declares no UI-node `events` keyed to actions. Shipping that sentence would have replaced one unauthorable surface with a pointer to a non-existent one, which is the exact hazard this card exists to remove. The NOTE now points at the real JSON face — `handlerKeyRefusal()` and the node-type spelling PR objectstack-ai#6498 established. ## Consumer verification | repo | result | control | |:--|:--|:--| | objectui (re-taken here) | 5 occurrences / 5 files on `origin/main`, **zero composition consumers** | `BaseSchema` → 429 files, fires; absent-token → 0 | | objectstack (re-taken here) | **0** | `BaseSchema` fires in the same corpus | | cloud | **0** —⚠️ INHERITED, not re-taken | live substituted control `@object-ui/*`, 16 files | | hotcrm | **0** —⚠️ INHERITED, not re-taken | live substituted control `@object-ui/*`, 3 files | The cloud and hotcrm legs are carried forward from the published reading on objectstack#15886 and are **not** presented as readings this seat took; this container holds no access to either repo. Reverse verification against the rebuilt `dist` rather than a cache: the built zod barrel exposes **211** named exports, the removed symbol is absent from it, and three sibling controls (`HTMLAttributesSchema`, `BaseSchema`, `ClassNameStylePropsSchema`) all resolve. ## Acceptance notes **The changeset's level came from the gate's own verdict, not from a sibling card.** `check-changeset-presence` scored this change `@object-ui/types`, "Scored `minor` at most, never `major`", so the declaration is `minor`. **On the BREAKING banner (review F2), answered explicitly.** The reviewer is right that the distinction I originally drew from objectui#9040 — "that one had a live consumer face, this has none" — is **not supported**: 9040 also recorded a zero in-repo census and took the banner anyway, and both removals produce an external compile error. I withdraw that reasoning. The banner is nonetheless omitted, for a different and narrower reason: **this card's ruling names the banner as a conditional and the condition was not met.** The ruling states that a live import anywhere means "the ruling stays retire but the changeset becomes BREAKING and the removal needs ADR-0087's conversion path rather than a plain delete". The four-repo census came back zero, so the plain-delete branch is the one the ruling itself selects. That is a ruled branch, not a house-style judgement, and it is not mine to override; 9040 is a different card under its own ruling. The body still tells a consumer plainly that an external import breaks and gives the FROM/TO, which is what a CHANGELOG reader needs either way. **The fifth occurrence is left alone, and three instruments agree.** `.changeset/6124-handler-keys-json-refusal.md` says "`EventHandlersSchema` is objectui#6910's card". That is a scope statement about what objectui#6124 did not cover, it stays true after the removal, `check-changeset-overwrite` exists precisely to report editing a changeset you do not own, and AGENTS.md objectstack-ai#11 forbids re-addressing a published record. Not touched. **Dist residue (review F3), corrected count.** The removed symbol survives in the built output **3 times: 1 in `dist/zod/base.zod.d.ts` and 2 in `.js` files** (`zod/base.zod.js`, `zod/index.zod.js`) — all of them the NOTE's own prose carried through as a comment. No declaration and no export: a grep for either in `dist` returns 0. **Out-of-scope finding, filed rather than fixed here** — AGENTS.md's abridged JSON-protocol sketch publishes an optional `events` member typed as a record of event-name string to ActionSchema array as a `BaseSchema` member, and its action-system commandment authors one, while no schema declares the key and nothing reads it. Because `BaseSchemaCore` is `.passthrough()`, a node written from that sketch is kept by the parser, judged by nothing and run by nothing — a silent discard, and the carrier is the file agents read first. Filed as objectui#9553, whose own census has been corrected for the same instrument error described above. AGENTS.md is a governed surface and is not touched by this PR. **Gate readings.** Green here: the changeset family (presence, no-major, overwrite, claims), control-bytes, new-line-citations, handler-key-reads, spec-symbols, test-path-roots, unreferenced-sources, the package's `type-check`, and the package suite. `check:readme-exports` is **NOT MEASURED** locally — it exits 1 on an unbuilt tree and prints "the population COLLAPSED -- this run proves nothing", a prerequisite failure and not a finding; it needs a full repo build and belongs to CI. It cannot be moved by this diff in any case: **0** READMEs name the removed symbol, against control `BaseSchema` firing in 13 of 54 tracked READMEs. `check-governed-queue-guard` is CI-only; its surface list was read directly instead, and none of these paths is governed. **Clause-②: yes** — a published export is removed. The `needs:contract-review` carrier is the PM's to hang; no label was touched by this seat, on the card or here. Implemented-by: claude/issue-6910-retire-event-handlers-schema --- _Generated by [Claude Code](https://claude.ai/code/session_01L5xpA5q533BgTTNADibEFt)_ --------- Co-authored-by: Claude <noreply@anthropic.com>
Fixes #6250
All measurements below are on
076ed3b51, branched fromorigin/main7975f2d85, withpackages/typesbuilt fresh.Before → after, as a reading
The seven
components-feedback-toast/*and sevencomponents-feedback-sonner/*SchemaExamplefixtures hung an action object offonClick. Parsing each fixture against the mirror its owntypeselects:Every one of the 14 was the same issue, on the ENVELOPE and not on any variant —
ButtonSchema.onClickisz.function()(zod/form.zod.ts:179):{"code":"invalid_type","expected":"function","path":["onClick"], "message":"Invalid input: expected function, received object"}The census, run on the shape rather than on a literal
A grep for
"action": "toast"under-counts by construction: the sonner half spells the same shape{ action: 'sonner', … }, and one fixture spells it{ action: { label, onClick } }. So the sweep walks every catalog entry at every depth for any key that reads as a handler slot (/^on[A-Z]/orevents), bucketed by the value's kind:The 14 object-valued hits were exactly the two directories this card names — no others anywhere in the 430-entry corpus. Independent corroboration:
docs/audits/2026-08-zod-to-json-schema-fidelity.md:317counted the same 14, from a different instrument, before this card was filed. That audit is a dated snapshot and is deliberately left as written.The remaining
string=1iscomponents-feedback-toaster/with-toast-trigger.json'schildren[0].onClick: "toast(\"Hello from ObjectUI!\")"— the handler-EXPRESSION dialect, which is #6182's open decision and a different shape. Untouched on purpose; a sweep that banned handler keys outright would be answering #6182 by accident.What actually runs, measured rather than picked for idiom
ActionRunner's runnable vocabulary isscript | url | modal | flow | api | form | navigation(builtinExecutors,core/src/actions/ActionRunner.ts:845). Notoast, nosonner— so{ action: 'toast' }had no dispatcher even if something had read it.packages/react,packages/core,packages/components,packages/layout. EveryonClickhit is a call of a function (await action.onClick()).ComponentRegistry.register('toast', …)and('sonner', …)DO run: each renders its own trigger button and calls sonner'stoast()from its handler.type: 'toast'ortype: 'sonner'fixtures existed anywhere in the corpus. Positive control — the same search finds 5type: 'toaster'fixtures. The registered spelling had no demo at all; the demos used an unregistered one.onClickis a member ofSDUI_DOM_PASS_THROUGH_KEYS(core/src/utils/dom-props.ts:88), so the action object reached the rendered button's DOM listener slot. Clicking it throws:That is pinned as a counter-probe, so "the old shape did nothing" is a measurement taken in this harness rather than a claim inherited from the card.
The key rule the corrections follow
Only keys that the governing schema declares AND the renderer reads:
toastsonnertitle,description,variant,duration,classNamemessage,title,description,variant,buttonLabel,buttonVariant,classNamebuttonLabel,buttonVariant— not usedaction,onDismiss,position— not usedSonnerSchemadeclaresbuttonLabel/buttonVariant;ToastSchemadoes not, though its renderer reads both. That asymmetry is why the sonner demos carry per-demo trigger labels and the toast demos render the defaultShow Toast. Teaching them ontoastwould have re-introduced an undeclared key into the fixtures this card is cleaning — #6161 set the posture on these same pages ("a key a renderer genuinely reads would have been routed out as an undeclared capability rather than deleted"). Routed out as #6496.Two demos had no working spelling, and that is why they changed premise
The
toastrenderer has no in-toast action button and no dismiss callback; thesonnerrenderer has no promise form. So "With Action", "With Undo Action" and "Promise Toast" could not be corrected into working demos of what their headings promised. They now demonstrate theinfo,warning,descriptionandbuttonVariantsurfaces that do run, and the pages follow. Curated titles for those five entries went intosrc/catalog-meta.json— the sidecar the generator only ever reads — so both the docs page and the standalone catalog gallery read correctly without renaming any fixture or changing any catalog id.index.tsis regenerated byscripts/regenerate-catalog-index.py;--checkwas green on the untouched tree first, so the 15/10 diff there is only those five entries.The missing capability is filed as #6496, not built here.
Overlap with an open card — needs your call, not mine
#6347 is still open and this PR lands two of its four items. It independently measured that
sonner.mdxdocumentsduration(whichSonnerSchemadoes not declare and the renderer does not pass) and that its "With Action" section renders a fixture that is abutton, not a sonner node. Both are on a page inside this card's declared file face, both are the same defect class, and both had their correct form already pinned bySonnerSchemaplus the renderer — so they are corrected here rather than left contradicting the fixtures beside them. Theactionrow went with them, on the same evidence.#6347's
button-group.mdxhalf —value,selectionMode, and the whole Selection Mode section — is untouched by this PR, and that card should stay open for it.content/docs/components/basic/button-group.mdxis not in this diff.Beyond the declared file face — declared, not slipped in
examples/schema-catalog/test/form-control-dom-leak-5632.test.tsx—NODE_CENSUS.button140 → 126. That is an exact census, not a shrink-only baseline, and its own header sanctions this case: "These move when the CATALOG is authored, not when a renderer changes." The gate's diff moved exactly one number, by exactly 14 — itself a corroboration of the census above. No renderer was touched.examples/schema-catalog/src/catalog-meta.jsonand the regeneratedsrc/index.ts— described above.content/docs/components/form/button.mdxwas in the dispatched face and is not in this diff: the shape census found no handler-object payload incomponents-form-button/*, and line 64'sonClick?: () => void | Promise<void>is accurate toButtonSchema. A measured non-edit.Clause ② — public surface, following the re-export chain
No public surface is touched. Checked three ways, none of them a symbol-name grep:
packages/is in this diff at all — so no published package's entry, and no chain from one, can reach a changed file.examples/schema-catalog/src/index.ts) has an identical export-statement set before and after — same five statements, same signatures, only line numbers shifted by the five addedtagsentries. It contains noexport *; its one re-export isexport type { Example, ExampleMeta } from './types.js', andtypes.tsis untouched.@object-ui/example-schema-catalogisprivate: trueand matched by the changesetsignorepattern@object-ui/example-*. Its only consumer in the workspace is@object-ui/site, which is itself inignore. The chain terminates at an app, never at a published package.Corroborated by
check:readme-exportsandcheck:entry-guard, both green.Tests
Two pins, one per half of the defect.
examples/schema-catalog/test/toast-demo-dispatch-6250.test.tsx(new) — renders each of the 14 demos against a real<Toaster />, clicks the trigger, and asserts the authored strings land in a toast node. Toasts are identified by node identity, not text: sonner's store is module-global and replays to every newly mounted<Toaster />, which was measured —basic-toastandsuccess-toastshare a description and a text query found it twice. Novi.mock('sonner'): sonner is not a dependency of this package, so the specifier would resolve to a different module than the renderer imports — a mock that cannot fail.examples/schema-catalog/test/component-fixture-declared-keys.test.ts— the finding(examples): the live SchemaExample fixtures on four component pages teach the same invented keys the prose blocks just stopped teaching #6157 pin assertedfixture.type === 'button'and destructuredfixture.onClick, i.e. it pinned the exact branch this card removes. Measured red first (6 failed / 10 passed), then replaced rather than reworded: what finding(examples): the live SchemaExample fixtures on four component pages teach the same invented keys the prose blocks just stopped teaching #6157 established — the toast variant value is a declaredToastSchemamember, withdestructiverefused — is carried forward against the top-levelvariantthese nodes now declare, counter-probe intact. A corpus-wide census assertion was added, with a positive control that the walker really descends (it names the one nested handler key the corpus still carries).Reverse verification — predicted RED, observed RED
The fix was committed first, then one fixture (
components-feedback-toast/destructive.json) was reverted to the retired shape. The mutation was proved on disk before any reading —grep -c '"action": "toast"'= 1,grep -c '"type": "toast"'= 0, andgit hash-objectdiffering from the HEAD blob — and restored through anEXIT INT TERMtrap using an absolute path.Reverting one fixture turned 7 assertions red across both files:
Restore proved byte-identical (
git hash-object==git rev-parse HEAD:<path>=b4a37b1c1, both non-empty;git diff HEADempty), and both files returned to green — 36 passed (36).Gates — all at
076ed3b51, each quoted from its own verdict lineExit codes captured before any pipe.
check:doc-types✅ Every documented component type is registered.(184 docs, 1064 blocks, 895typeliterals)check:doc-snippetsEvery covered documentation snippet compiles against the built types.—Semantic phase: 267 of 267 block(s) judged, 0 failed.check:doc-fences✅ check:doc-fences — every TypeScript block in 223 document(s) is fenced ts/tsx/typescript…check:docs-route-closure✅ gauge: 1349 modules crawled from 148 route roots (144 MDX)… 18 of 46 workspace packages stay OUTSIDE the closurecheck-doc-linksLinks are valid across 17 scan roots.check:control-bytes✅ check-control-bytes: OK (scanned 5363 tracked text file(s); skipped 85 binary).check:entry-guard✓ check:entry-guard: 50 scripts/ file(s) — no entry guard outside the baseline…check:readme-exports✅ check-readme-exports: OK (43 README(s)… 378 self-imports judged (378 real, 0 wrong-path, 0 fabricated))check:vi-mock-specifiers✅ check-vi-mock-specifiers: OK (3816 tracked source file(s)…)check:phantom-deps✅ Every in-scope import is declared by the package that publishes it.regenerate-catalog-index.py --checkexamples/schema-catalog/src/index.ts is up to date (430 entries).check-changeset-presence✅ No source of a released package changed in this range, so no changeset is owed.(1 changeset added anyway, empty frontmatter — the repo's first-class "declares no release")check-changeset-no-major✅ No changeset declares amajorbump.check-changeset-fixed✅ All workspace packages are in the changeset fixed group.vitest examples/schema-catalog/ scripts/__tests__/catalog-index-regenerable-4633.test.tsTest Files 15 passed (15) · Tests 1824 passed (1824)pnpm --filter @object-ui/example-schema-catalog type-checktsc --noEmit && tsc -p tsconfig.test.json, no outputTwo non-zero exits that were NOT MEASURED, excluded from the table and named here:
check:readme-exportsfirst exited 1 with "3 self-import(s) could not be judged —@object-ui/plugin-ai's type entry./dist/index.d.tsis not on disk — runpnpm buildfirst", and the catalogtype-checkfirst exited 2 with twoTS2882s naming@object-ui/plugin-ganttand@object-ui/plugin-mapin a file this PR does not touch. Both were missingdist/, not defects; both went green after building those packages. Neither is counted as a failure.Lint — a measured narrowing, not a skipped run
Repo-wide lint is CI's run. Locally the narrowing is measured, from eslint's own config rather than from a guess about which files count:
.mdx,.jsonand.mdcome backFile ignored because no matching configuration was supplied— 16 of the 19 changed files are outside the configured population, so a green on them would have been a non-reading, not a pass.--format json. The three changed files that ARE in the population (.ts/.tsx) report 0 errors, 0 warnings. The bounding package's whole population is 17 files, all genuinely linted: 0 errors, 1 warning —'ExampleMeta' is defined but never usedin the generatedsrc/index.ts, present verbatim on7975f2d85and on a line this diff does not touch. Left alone; the generator owns that file.eslint.config.jsconfigures no type-aware linting — noprojectService, noparserOptions.project, noproject:anywhere in it — so no rule's verdict on a file outside this diff can depend on this diff.Filed in passing
toasterdemos and page teach aproviderkey thatToasterSchemadoes not declare and the renderer does not read #6494 — thetoasterdemos and page teach aproviderkeyToasterSchemadoes not declare and the renderer does not read. Two "provider" demos render byte-identically. Same defect class, different shape, and the page makes a capability claim, so it is a contract question rather than a typo.ToastSchemaand thetoastrenderer disagree in BOTH directions — two keys read but undeclared, two declared but unread #6496 —ToastSchemaand its renderer disagree in both directions:buttonLabel/buttonVariantread but undeclared,action/onDismissdeclared but unread. This is what constrained the two decisions above.EventableSchema/UIEventHandler, with no mirror, no extender and no reader #6497 — the action-object dialect is already declared and exported:EventableSchema.onClick?: UIEventHandler | string(api-types.ts:278), public indist/index.d.ts, with no zod mirror, no component schema extending it, and no reader. It refines this card's "declared nowhere" and is a direct input to the [Decision] Is an authored handler EXPRESSION a supported dialect? 56 mirrors say function, 11 say string, and both appear in files that mirror the other #6182 / finding(types): 28 zod-mirror keys are declaredz.function(), which NO JSON document can satisfy — 14 in-repo corpus files author them and are silently invalid #6124 decision — the declaration half is not a blank page.All three unassigned,
findinglabel only, no grading.The fence — held
⛔ No action union declared on
ButtonSchema.onClick. ⛔ No dispatcher built. ⛔ Notoastorsonnerexecutor added toActionRunner. ⛔ Nopackages/file changed at all. #6249 is out of scope here and remains open. The maintainer's route is not foreclosed by anything in this diff — and #6497 is new evidence for it.Draft, no auto-merge: the PM lands this.
Generated by Claude Code
Generated by Claude Code