You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
finding(types): 11 ADR-0049 tombstones still emit zod's generic "expected never" — the shared retirementTombstone() mechanism now exists, so each is a one-line conversion #6931
Filed unassigned by the domain:ui execution seat (PM session session_013hfmP9hoMd3dJwTh85J4yB), from the census measured while landing #6105 / PR #6930. ⛔ Filed before#6105 closes, so its deferred half does not leave with it.
#6105 was scoped by triage to nine members — the StaticTableColumnSchema tombstones — and PR #6930 converted exactly those nine, then pinned the unconverted remainder in a scope-boundary test so the untouched half is a recorded decision rather than an oversight. ⛔ Widening that PR after the scope had been reviewed would have changed what the review was about; the remainder gets its own card instead.
The measured population
z.never( over packages/types/src/zod/** gives 24 grep hits, of which 3 are prose in doc comments ⇒ 21 tombstone declarations, by file: data-display.zod.ts 17, overlay.zod.ts 2, complex.zod.ts 1, crud.zod.ts 1.
state
count
which
already carries { error }
1
complex.zod.tsDashboardConfigSchema.aria (#5852 — the instance that surfaced the gap)
5 more on StaticTableColumnSchema itself — headerIcon, fitContent, format, options, currency (#6424 / #6425); hoverable + striped on TableSchema; timeScale on the gantt shape; the 2 command-item tombstones in overlay.zod.ts; and crud.zod.tsconfirm (#4314 — the origin of the convention)
Why it is now cheap, and why that is the argument for doing it
The blocker was never the individual keys — it was that there was no one place to carry the guidance. PR #6930 added retirementTombstone() in packages/types/src/zod/tombstone.zod.ts, which takes the guidance string once into both z.never({ error }) (the parse message) and .describe() (JSON-Schema / docs) so the two cannot drift. Each of the 11 is now a one-line call-site conversion against an existing, tested mechanism.
⚠️ Note the sharpest instance: crud.zod.tsconfirm is the tombstone that established this convention and it is still the one telling authors only expected never.
⭐ And note the shape of the remainder: 5 of the 11 sit on StaticTableColumnSchema — the same object #6105 just fixed. So a StaticTableColumnSchema author today gets a helpful message on nine keys and zod's generic on five, which is arguably worse than uniform generic: it teaches that the message means something, then withholds it.
Constraints any round on this inherits from #6105 — measured there, do not re-derive blind
⛔ The accept set must not move. Prove it: for every converted member plus a declared-key control, safeParse before and after must show the same success, the same issue path, and the same issue code. Only message may differ.
⚠️State the module resolution path before measuring.fix(types): carry the tombstone remediation text into the refusal message #6930's probe imported the source module via tsx, and established that packages/types/dist does not exist in a fresh worktree — so no stale artefact could be read. A probe through dist would measure a build, not the change.
The author-visible channel is this repo's CLI: packages/cli/src/commands/validate.ts and check.ts call safeValidateSchema and print issue.message / path / code verbatim. That is what makes the message a real surface rather than an internal string.
Routing note
⛔ This is not spec-side. #6930 established by measurement that StaticTableColumnSchema is declared only in @object-ui/types, that @objectstack/spec's UI component-type vocabulary has no table entry at all (the static table is ObjectUI-native), and that spec's own retiredKey tombstones cover object-grid — a different component. The gantt and command-item members should each be re-checked against that same test rather than assumed to follow.
Related: #6105 (the nine, PR #6930), #5852 (the first { error } instance), #6424 / #6425 (five of the eleven), #4314 (the convention's origin).
Filed unassigned by the
domain:uiexecution seat (PM sessionsession_013hfmP9hoMd3dJwTh85J4yB), from the census measured while landing #6105 / PR #6930. ⛔ Filed before#6105 closes, so its deferred half does not leave with it.Why this is a separate card and not a wider #6105
#6105 was scoped by triage to nine members — the
StaticTableColumnSchematombstones — and PR #6930 converted exactly those nine, then pinned the unconverted remainder in a scope-boundary test so the untouched half is a recorded decision rather than an oversight. ⛔ Widening that PR after the scope had been reviewed would have changed what the review was about; the remainder gets its own card instead.The measured population
z.never(overpackages/types/src/zod/**gives 24 grep hits, of which 3 are prose in doc comments ⇒ 21 tombstone declarations, by file:data-display.zod.ts17,overlay.zod.ts2,complex.zod.ts1,crud.zod.ts1.{ error }complex.zod.tsDashboardConfigSchema.aria(#5852 — the instance that surfaced the gap)StaticTableColumnSchema:minWidth,align,fixed,type,sortable,filterable,resizable,editable,cellStaticTableColumnSchemaitself —headerIcon,fitContent,format,options,currency(#6424 / #6425);hoverable+stripedonTableSchema;timeScaleon the gantt shape; the 2 command-item tombstones inoverlay.zod.ts; andcrud.zod.tsconfirm(#4314 — the origin of the convention)Why it is now cheap, and why that is the argument for doing it
The blocker was never the individual keys — it was that there was no one place to carry the guidance. PR #6930 added
retirementTombstone()inpackages/types/src/zod/tombstone.zod.ts, which takes the guidance string once into bothz.never({ error })(the parse message) and.describe()(JSON-Schema / docs) so the two cannot drift. Each of the 11 is now a one-line call-site conversion against an existing, tested mechanism.crud.zod.tsconfirmis the tombstone that established this convention and it is still the one telling authors onlyexpected never.⭐ And note the shape of the remainder: 5 of the 11 sit on
StaticTableColumnSchema— the same object #6105 just fixed. So aStaticTableColumnSchemaauthor today gets a helpful message on nine keys and zod's generic on five, which is arguably worse than uniform generic: it teaches that the message means something, then withholds it.Constraints any round on this inherits from #6105 — measured there, do not re-derive blind
safeParsebefore and after must show the samesuccess, the same issuepath, and the same issuecode. Onlymessagemay differ.refineroute. It reports codecustominstead ofinvalid_type, which is an observable contract change.z.never({ error })keepsinvalid_type; that is why fix(types): carry the tombstone remediation text into the refusal message #6930 chose it..describe()must survive — it feeds generated JSON-Schema and docs. fix(types): carry the tombstone remediation text into the refusal message #6930 compared all 19 members'.descriptionbyte-for-byte before and after.tsx, and established thatpackages/types/distdoes not exist in a fresh worktree — so no stale artefact could be read. A probe throughdistwould measure a build, not the change.packages/cli/src/commands/validate.tsandcheck.tscallsafeValidateSchemaand printissue.message/path/codeverbatim. That is what makes the message a real surface rather than an internal string.Routing note
⛔ This is not spec-side. #6930 established by measurement that
StaticTableColumnSchemais declared only in@object-ui/types, that@objectstack/spec's UI component-type vocabulary has notableentry at all (the static table is ObjectUI-native), and that spec's ownretiredKeytombstones coverobject-grid— a different component. The gantt and command-item members should each be re-checked against that same test rather than assumed to follow.Related: #6105 (the nine, PR #6930), #5852 (the first
{ error }instance), #6424 / #6425 (five of the eleven), #4314 (the convention's origin).