Repository navigation
refactor(types)!: derive the object-form and object-calendar spec keys, rename the legacy zod ActionSchema (#25923) - #26751
Conversation
… legacy zod ActionSchema Work item 4 of #25923. ObjectFormSchema gains contentLayout and confirmOnDiscard, ObjectCalendarSchema gains locale and loading, each the ComponentPropsMap row member by reference on both faces. The zod ActionSchema (legacy type: 'action' node) is renamed CRUDActionSchema so @object-ui/types/zod no longer publishes the spec's ActionSchema name for an unrelated contract. zod-mirror-parity.test.ts gains the spec-only census over the derived spec pairs. Claude-Session: https://claude.ai/code/session_01WGufzhgTn8yFwqXxanJd4c Co-authored-by: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WGufzhgTn8yFwqXxanJd4c Co-authored-by: Claude <noreply@anthropic.com>
The member-count pin in object-view-slot-key-lists moves from 69 to 71: `contentLayout` and `confirmOnDiscard` are now declared by reference to `ComponentPropsMap['object-form']`, and the `form` slot carries both. Claude-Session: https://claude.ai/code/session_01WGufzhgTn8yFwqXxanJd4c Co-authored-by: Claude <noreply@anthropic.com>
…pace importer (#25923) The census walks the whole `@objectstack/spec/ui` surface to pair each mirror with its same-name spec schema, so the namespace import trips the #3090 `no-restricted-imports` entry for the spec `FormFieldSchema`. It reads the schemas at runtime only; the disable carries that reason, as the other sanctioned namespace importers do. Claude-Session: https://claude.ai/code/session_01WGufzhgTn8yFwqXxanJd4c Co-authored-by: Claude <noreply@anthropic.com>
Contract reviewServed-tier: Inputs: card #25923 body and every comment through the os-dev-report 6445173979; PR #26751 body, file list (15 files, +307/-50), zero PR comments and reviews, the net diff against ① Derived judgments
② Semver level
③ Boundary flags
Implemented-by: VERDICT: FAIL |
…ma (#25923) The enhanced-actions page still named the zod schema `ActionSchema`; the const is `CRUDActionSchema` on `@object-ui/types/zod` since the rename. Claude-Session: https://claude.ai/code/session_01WGufzhgTn8yFwqXxanJd4c Co-authored-by: Claude <noreply@anthropic.com>
Contract reviewServed-tier: Second record on this PR; it supersedes the FAIL record on ① Derived judgments
② Semver level
③ Boundary flags
Implemented-by: VERDICT: PASS |
维护者速读 (席位终稿)
席位意见:接受。契约复核 PASS(6445777977)。首轮 FAIL 的 Lint UI 红和一句过时文档,都已在新 head 修好。 席位核对 · ACCEPT ·
|
Requested by Yibo Wang · project thread
Part of #25923 (work item 4 only; item 3 and the FormField follow-up stay on the card)
Clause-②: yes (narrowing)
Metadata-protocol: narrowed
Skills-docs: none —
skills/objectstack-ui/references/react-blocks.mdalready teachescontentLayoutandconfirmOnDiscard; object-calendarlocaleandloadingare taught only by the spec rows'.describe()text, with noskills/**orui/content/docspage; noskills/**page names the zodActionSchema, and the two ui docs pages that imported it are updated in this diff维护者速读
ActionSchema对 objectui 无关的旧type: 'action'节点 schema。真实配对上的缺口是 11 个键。ObjectFormSchema.contentLayout/confirmOnDiscard、ObjectCalendarSchema.locale/loading(均为节点键,不是 refactor(types,plugin-calendar,plugin-gantt,plugin-list,plugin-view)!: flat object-calendar / object-gantt keys leave the published schemas; producers emit the block #26411 移走的日历字段名键)。FormFieldSchema上 spec 表单视图条目的键(两层同名词汇),逐键登记在zod-mirror-parity.test.ts的普查里:2 translated、4 carried-not-rendered、1 spec-retired。@object-ui/types/zod的ActionSchema改名CRUDActionSchema:0 个生产导入方,改名比退役破坏最少;接受集不变。Clause-②: yes (narrowing)、Metadata-protocol: narrowed,changeset 带 BREAKING Before/Now/Fix。@object-ui/types的 39 个包 type-check 108/108 通过。Measurement (main
43731031)The key-drift probe pairs each
@object-ui/types/zodmirror with the spec schema of the same export name in@objectstack/spec/data∪@objectstack/spec/ui, and each node mirror with itsComponentPropsMaprow bytypeliteral. A key the spec declares that the mirror neither declares nor refuses is "spec-only".ActionSchema↔ specActionSchemaActionSchemais the legacytype: 'action'node and shares no vocabulary with the spec's action metadata. This is the card's "33".FormFieldSchema↔ specFormFieldSchemaObjectFormSchema↔ComponentPropsMap['object-form']ObjectCalendarSchema↔ComponentPropsMap['object-calendar']Real gap over the real pairs: 11 keys. After this PR: 0 unrecorded, judged by the new census in
zod-mirror-parity.test.ts.Per-key disposition
ObjectFormSchema.contentLayoutSpecObjectFormProps['contentLayout'], zod.shape.contentLayout)ModalFormreads itObjectFormSchema.confirmOnDiscardModalForm,DrawerFormread itObjectCalendarSchema.localeplugin-calendarresolveAuthoredLocale(rest.locale)ObjectCalendarSchema.loadingplugin-calendarresolveExternalLoading(rest.loading)FormFieldSchema.fieldnormalizeSectionFieldwrites it as the runtimenameFormFieldSchema.helpTextdescriptionFormFieldSchema.immutableFormFieldSchema.keyFieldFormFieldSchema.disclosureFormFieldSchema.precisionscaleand the object field's metadataFormFieldSchema.publicPickerretiredKey()tombstone refuses it with its remedyNo key needed a new
z.neverrefusal: the only retired key (publicPicker) is already refused by the spec with its remedy, and objectui's runtime layer never had it.Seat guard on the two calendar keys:
localeandloadingare members the spec authors on theobject-calendarnode and the renderer reads off the node. They are not the calendar field-name keys PR #26411 moved to the hand-off type, so nothing returns to the published face that item 1 took off it.ActionSchema: rename, not retire
Importers of the zod
ActionSchemaon main: 0 production, 7 test files, 2 docs pages. Retiring it would also break theactionarm of the CRUD discriminated union and theactionsarrays ofCRUDDialogSchema,DetailSchemaand the chain, which all hold it. Renaming changes only the export name, so it breaks fewest. The TypeScript twin keeps its deprecatedActionSchemaname in@object-ui/types.What changes
ui/packages/types/src/zod/objectql.zod.ts,ui/packages/types/src/objectql.ts: the four keys, by reference on both faces;ObjectFormSlotKeycarries the two form keys.ui/packages/types/src/zod/crud.zod.ts,index.zod.ts:ActionSchema→CRUDActionSchema, every internal reference with it.object-view-slot-key-lists.test.tspinsObjectFormSchemaat 71 members (was 69)..changeset/25923-spec-only-keys-crud-action-schema.md:@object-ui/typesminor, BREAKING Before/Now/Fix.Tests
zod-mirror-parity.test.tsis extended (no new gate) with a census, "every spec-only key over the spec pairs is derived, refused or recorded":contentLayout: 'tabs'refused at pathcontentLayout;ActionSchemaand hasCRUDActionSchema, while@objectstack/spec/uistill hasActionSchema.Reverse check: removing the
contentLayoutderivation turns the census red namingObjectFormSchema.contentLayout; restored afterwards.Acceptance notes
immutable,keyField,disclosureandprecisionare copied bynormalizeSectionFieldbut no renderer reads them. That is recorded here as "declared, not rendered"; no reach was measured, so no card is filed for it.ADR-0087 disposition is
not-required (no-migration-prescription).runtime-export-retiredwould fit better, but that category reads only a package's main entry and refuses an operand declared in a*.zod.ts, and this export is on the./zodsubpath.ADR-0087 marker (seat ruling, 2026-10-27):
not-required (no-migration-prescription)stands, as on PR refactor(types,plugin-calendar,plugin-gantt,plugin-list,plugin-view)!: flat object-calendar / object-gantt keys leave the published schemas; producers emit the block #26411. The gate cannot see@object-ui/typesexports yet, and check-adr-0087-registration: PACKAGE_ROOTS omits ui/packages, ui/apps and ui/examples, so no @object-ui package can use the runtime-export-retired disposition #26220 (PACKAGE_ROOTSomitsui/packages) carries that gap.immutableis declared on the mirror but not rendered by objectui (contract review 6445632813 ③.5). It folds into types: the strict authoring face accepts spellings the spec refuses (object-calendar flat keys), 74 zod mirrors silently strip unknown keys, and the list view's options bag is a second contract #25923's FormField follow-up and is recorded on the card at landing.Verification
Head
38c2841a(readings below were taken on96c8d55d, withmain94bab5a2merged in;d18ba32eadds a reasonedeslint-disable-next-line no-restricted-importson the census'simport * as SpecUi from '@objectstack/spec/ui', the formspec-ui-schema-reexports.test.tsuses, which turned Lint UI green;38c2841acorrectsenhanced-actions.mdxto nameCRUDActionSchema). The vitest, gates and type-check readings below were taken atb5f1b90b(before the merge); after the merge,@objectstack/specwas rebuilt andcd ui && pnpm exec vitest run packages/types/re-run under os-verify-lock: 393/393 files, 10691 passed, exit 0. #26365 is still an open draft; it editszod-mirror-parity.test.tsin different regions, and whichever lands later mergesmainand re-runs that file.node scripts/pm/dispatch-gates.mjs --ran: 34 derived, 34 run, 0 NOT-MEASURED; every exit 0.pnpm --dir ui exec vitest run scripts/first exited 1 on an unbuilt@objectstack/coredist in this container, and exited 0 once it was built.cd ui && pnpm exec vitest run packages/types/ packages/plugin-form/ packages/plugin-calendar/: 660/660 files, 13570 passed, 96 skipped, exit 0.cd ui && pnpm exec turbo run type-check --filter='...@object-ui/types' --concurrency=2 --continue: 39 packages in scope, 108/108 tasks successful, exit 0.node scripts/check-platform-checklist.mjs --changed-from origin/main: exit 0 (no anchored file in the change set).node scripts/check-adr-0087-registration.mjs --base origin/main: exit 0.🤖 Generated with Claude Code
https://claude.ai/code/session_01WGufzhgTn8yFwqXxanJd4c