Uh oh!
There was an error while loading. Please reload this page.
fix(types): carry the tombstone remediation text into the refusal message - #6930
Merged
Merged
Conversation
…sage
The nine ADR-0049 tombstones on `StaticTableColumnSchema` refused an authored
value at the right path, but the `.describe()` remediation string never reached
the author: `.describe()` is schema metadata, so what an author read was zod's
generic `Invalid input: expected never, received string`. Loud refusal is the
ruled outcome and half its payload was being dropped.
`retirementTombstone()` (`zod/tombstone.zod.ts`) is the one shared mechanism:
the guidance string is written ONCE and carried into both `z.never({ error })`
(the parse-time issue message) and `.describe()` (generated JSON-Schema/docs,
byte-identical). One string, so the two channels cannot drift apart.
Accept set untouched — same `success`, same issue `path`, same issue `code`
(`invalid_type`) for all nine, measured member-by-member before and after.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013hfmP9hoMd3dJwTh85J4yB
This was referenced Aug 31, 2026
Contributor
✅ Console Performance Budget
The eager closure is every chunk the entry reaches through static imports — what the browser fetches and parses before the app renders. The entry chunk on its own is a small fraction of it. 📦 Bundle Size Report
Size Limits
|
os-sam
marked this pull request as ready for review
August 31, 2026 01:28
Uh oh!
There was an error while loading. Please reload this page.
os-sam pushed a commit
that referenced
this pull request
Aug 31, 2026
…ion text `retirementTombstone()` (objectui#6105 / PR #6930) writes a guidance string ONCE into both author-facing channels — `z.never({ error })`, the parse-time issue message, and `.describe()`, the generated JSON-Schema and docs surface. Nine tombstones on `StaticTableColumnSchema` were converted there; eleven declarations were left on the bare `z.never().optional().describe(...)` spelling and kept answering with zod's generic `Invalid input: expected never, received string` — which names the key and says nothing about why it was retired or what to write instead. Five of the eleven sat on `StaticTableColumnSchema` itself, so its author read guidance on nine keys and zod's generic on five: a shape that teaches the message means something, then withholds it. Converted here: `headerIcon` / `fitContent` / `format` / `options` / `currency` (StaticTableColumnSchema), `hoverable` / `striped` (TableSchema), `timeScale` (TimelineSchema), `type` on both `MenuItemSchema` union arms, and `confirm` (ActionSchema) — the key that established the convention and was the last one still emitting the generic message. The accept set does not move. Measured member-by-member on the SOURCE modules (tsx; `packages/types/dist` does not exist in a fresh worktree): for all 11 conversions, the 9 already-converted controls and 6 live-value controls, `safeParse` reports the same `success`, `path`, `code` (`invalid_type`) and `expected` (`never`) before and after; only the message differs. All 132 `.description` values on the five affected schemas are byte-identical. `MenuItemSchema` is a union, so its top-level issue stays zod's own `invalid_union` / `Invalid input` at path `[]` and the guidance rides the per-arm issues; that is pinned in the tests rather than glossed. #6930's scope-boundary pin — which asserted the remaining seven still emitted the generic message — is flipped rather than deleted: it now holds them to the same standard as the nine, with the live column and table as in-test non-vacuity controls. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013hfmP9hoMd3dJwTh85J4yB
akarma-synetal pushed a commit
to akarma-synetal/objectui
that referenced
this pull request
Sep 1, 2026
…ion text (objectstack-ai#7005) `retirementTombstone()` (objectui#6105 / PR objectstack-ai#6930) writes a guidance string ONCE into both author-facing channels — `z.never({ error })`, the parse-time issue message, and `.describe()`, the generated JSON-Schema and docs surface. Nine tombstones on `StaticTableColumnSchema` were converted there; eleven declarations were left on the bare `z.never().optional().describe(...)` spelling and kept answering with zod's generic `Invalid input: expected never, received string` — which names the key and says nothing about why it was retired or what to write instead. Five of the eleven sat on `StaticTableColumnSchema` itself, so its author read guidance on nine keys and zod's generic on five: a shape that teaches the message means something, then withholds it. Converted here: `headerIcon` / `fitContent` / `format` / `options` / `currency` (StaticTableColumnSchema), `hoverable` / `striped` (TableSchema), `timeScale` (TimelineSchema), `type` on both `MenuItemSchema` union arms, and `confirm` (ActionSchema) — the key that established the convention and was the last one still emitting the generic message. The accept set does not move. Measured member-by-member on the SOURCE modules (tsx; `packages/types/dist` does not exist in a fresh worktree): for all 11 conversions, the 9 already-converted controls and 6 live-value controls, `safeParse` reports the same `success`, `path`, `code` (`invalid_type`) and `expected` (`never`) before and after; only the message differs. All 132 `.description` values on the five affected schemas are byte-identical. `MenuItemSchema` is a union, so its top-level issue stays zod's own `invalid_union` / `Invalid input` at path `[]` and the guidance rides the per-arm issues; that is pinned in the tests rather than glossed. objectstack-ai#6930's scope-boundary pin — which asserted the remaining seven still emitted the generic message — is flipped rather than deleted: it now holds them to the same standard as the nine, with the live column and table as in-test non-vacuity controls. Claude-Session: https://claude.ai/code/session_013hfmP9hoMd3dJwTh85J4yB Co-authored-by: Claude <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for freeto join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes#6105
The nine ADR-0049 retirement tombstones on
StaticTableColumnSchemarefused theright keys at the right paths, but the
.describe()remediation string neverreached the author:
.describe()is schema METADATA. What an author who wrotealign: 'right'actually read was zod's genericInvalid input: expected never, received string— which key is wrong, nothing about why it was retired or whatto write instead. Loud refusal is the ruled outcome; half its payload was being
dropped.
Routing — settled by measurement before any code was written
The first triage touch left this open: the fix might belong in the spec's
error-guidance face (
objectstack packages/spec) rather than here, to be settledby reading which package owns the parse call. Measured, three ways, all
pointing here:
StaticTableColumnSchemais declared only in this repo(
packages/types/src/zod/data-display.zod.ts).@objectstack/specdeclaresno schema carrying these members —
grep minWidth packages/spec/src/ui/*.zod.tsis empty, and
accessorKeyappears there only inside a prose comment inconversions/registry.ts.(
packages/spec/src/ui/component-type-vocabulary.ts) has notableentry atall. The static
tableis an ObjectUI-native component; spec's nearbyretiredKeytombstones coverobject-grid, a different component.packages/cli/src/commands/validate.tsandcheck.tscallsafeValidateSchemafrom@object-ui/types/zod(→AnyComponentSchema→TableSchema→StaticTableColumnSchema) and printissue.message,issue.pathandissue.codeverbatim.So the parse producing the author-visible message for these keys is owned by
@object-ui/types. The card stays in this repo.The change — one shared mechanism, nine members
retirementTombstone()(new,packages/types/src/zod/tombstone.zod.ts) takes theguidance string once and writes it into both author-facing channels:
z.never({ error })for the parse-time issue message,.describe()for generatedJSON-Schema and docs. One argument feeding two channels is the point — the message
an author reads and the text the docs publish cannot drift apart, because there is
only one string.
DashboardConfigSchema.aria(objectui#5852) landed this spellingby hand; this is that spelling as a shared mechanism, not nine hand-written
strings.
Applied to exactly the nine keys triage named:
minWidth,align,fixed,type,sortable,filterable,resizable,editable,cell. Every describestring is carried through byte-identical — the diff changes only the call wrapper.
Authoring
align: 'right'on a static table column now reports:Clause ② — the accept set is unchanged, proved not assumed
Same probe run before and after, importing the source module
(
packages/types/src/zod/data-display.zod.ts) viatsx, neverdist—packages/types/distdoes not exist in a fresh worktree, so no stale artefactcan be read.
pathb/acodeb/amessage["minWidth"]= sameinvalid_type= same["align"]= sameinvalid_type= same["fixed"]= sameinvalid_type= same["type"]= sameinvalid_type= same["sortable"]= sameinvalid_type= same["filterable"]= sameinvalid_type= same["resizable"]= sameinvalid_type= same["editable"]= sameinvalid_type= same["cell"]= sameinvalid_type= sameOnly
messagemoved. Therefine-based route triage listed as the othercandidate was not taken precisely because it reports
customhere — a contractchange wearing a message change's clothes.
z.never({ error })keepsinvalid_type, andz.inputstill types the keynever, sotscstill refusesit at the authoring site first.
.describe()survives: all 19 members'.descriptionvalues compared beforeand after are byte-identical, the nine included.
Scope — deliberately nine, not the whole population
Mechanical
z.never(walk overpackages/types/src/zod/**: 21 tombstonedeclarations (24 grep hits, 3 of them prose in doc comments):
data-display.zod.tsStaticTableColumnSchema(the nine converted here + 5 later arrivals),hoverable+stripedonTableSchema,timeScaleon the gantt shapeoverlay.zod.tstypepair (objectui#6523)complex.zod.tsDashboardConfigSchema.aria— already carries{ error }(objectui#5852)crud.zod.tsconfirm(objectui#4314) — the tombstone convention's originConverted: the nine only. The remaining 11 still-generic tombstones are
reported, not touched — widening past what triage scoped would change the stated
scope after the fact. They are cheap follow-ups now that the mechanism exists.
The five later arrivals on the same shape (
headerIcon/fitContent,objectui#6424;
format/options/currency, objectui#6425) plushoverable/stripedare pinned as an explicit scope boundary test, so theunconverted half is a recorded decision with a test behind it rather than an
oversight.
Verification
Pinned in
packages/types/src/__tests__/static-table-narrow-surface.test.ts(3 new tests), on the message content, with a declared-key control parsing
green in the same test so no green can come from a vacuous parse. The
both-channels invariant is asserted derived (
message === describe) with twoliteral anchors beside it, since two empty strings are also equal, plus one full
literal pin on
align.Ablation, direction predicted in writing before the run. Predicted: RED in
exactly 2 of the 3 new tests (the nine-member loop on
align, and thealignliteral pin); the scope-boundary test and the pre-existing "REFUSES a column
authoring
align" test stay GREEN, since the accept set is untouched by themutation. Mutated the fact —
alignback to the barez.never().optional().describe(...)with the same text — undertrap ... EXIT INT TERMwith absolute paths from
git rev-parse --show-toplevel.Mutation proved on disk: anchored counts both directions (injected 1, removed 0)
and
git hash-objectmoved74c7bfa6…→4140e557…. No rebuild leg applies andthat is proved, not assumed: the suite imports
../zod/data-display.zodbyrelative source path and
packages/types/distdoes not exist.Observed:
Tests 2 failed | 32 passed (34)— the two predicted tests, by name.Restore proved both ways:
git diff HEADempty for the file andhash-objectback to the HEAD blob74c7bfa6…, restored withgit checkout HEAD --with an absolute path.Gates — all measured on
494a66e0, exit codes captured before any pipepnpm --filter @object-ui/types type-checktsc --noEmit && tsc -p tsconfig.examples.json && tsc -p tsconfig.test.json)pnpm exec vitest run packages/types/pnpm exec eslint .inpackages/types(plain form)node scripts/check-changeset-presence.mjscheck:control-bytescheck:self-importcheck:esm-specifierscheck:node-esm-loadcheck:phantom-depscheck:pre-install-import-graphcheck:readme-exportscheck:spec-symbolscheck:vi-mock-specifierscheck:vi-mock-inheritcheck:side-effects-arrayThe type-check genuinely covers the edited files rather than excluding them —
tsc --listFilesshowstombstone.zod.tsanddata-display.zod.tsin the mainprogram and
static-table-narrow-surface.test.ts+tombstone.zod.tsin thetsconfig.test.jsonprogram.check:published-distis red onmain, not from this branch: the finding is@object-ui/fields → dist/__tests__/numberInputBrowserReadings.d.ts, a packagethis diff never touches (4 files changed, all under
packages/typesand.changeset). Already tracked as objectui#6861.The helper is deliberately not re-exported from
index.zod.ts: nothingoutside
@object-ui/typesdeclares these schemas, so this adds no public API.Generated by Claude Code
Generated by Claude Code