Repository navigation
feat(spec,app-shell)!: a form view's type is its layout only — simple, tabbed or wizard; split, drawer and modal are retired with pane, splitSize and splitResizable - #27229
Conversation
…r wizard; split, drawer and modal retired with pane, splitSize and splitResizable FormViewSchema.type is now `simple | tabbed | wizard` (default `simple`), built with enumWithRetiredValues: `split`, `drawer` and `modal` are refused by name with prescriptions that name live replacements only. The split-only keys `sections[].pane`, `splitSize` and `splitResizable` become retiredKey() tombstones. `splitDirection`, `drawerSide`, `drawerWidth` and `modalSize` stay declared (console dialog sizing and the React ObjectForm block contract). ADR-0087 kit: D2 conversion form-view-presentation-types-removed (retired from the load path, retiredAfter 18.2.0), D3 entry ui-form-view-type-layout-only, STEP18_RATIONALE fragment, three RETIRED_KEYS_BY_MAJOR rows, liveness rows, removal-version JOIN row, and a pin test with a tree-scoped absence walk. Showcase task views re-spelled to tabbed / simple, with the drawer open mode shown on the list's navigation.mode. Reference docs, authorable surface and liveness counts regenerated. Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WGufziVeBj5ENSWqsDTaYe
Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WGufziVeBj5ENSWqsDTaYe
…llow the narrowed form view type The view-create form and the default view schema offered split, drawer and modal, which the spec now refuses at save. The package form spells its layout simple (its dialog is the caller's open mode). ui tests that pinned spec acceptance of the retired members are re-pinned to their refusal. Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WGufziVeBj5ENSWqsDTaYe
Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WGufziVeBj5ENSWqsDTaYe
📓 Docs Drift CheckThis PR changes 2 package(s): 28 hand-written doc(s) name something this change touched — list omitted above 15 rows. Re-derive on the tree named below: ⛔ 5 release-owned page(s) also affected — read-only, see AGENTS.md Documentation Guardrails. What this run could not see
Coarse fallback — 148 page(s) merely mention a changed package (the pre-#9192 predicate, kept for the deliberately-wide backstop): Which tree this was computed onThis run read A worktree cut from an older # while this PR is open — GitHub drops the merge commit once it closes
git fetch origin 8f298a4addc1ff9ba464b4f30c91c23678ae519b && git checkout 8f298a4addc1ff9ba464b4f30c91c23678ae519b
# afterwards, rebuild it from the two parents, which stay fetchable
git fetch origin ae16687ad430f4f9870ea5ba2bc9b63d6f41fc31 2c75635eb43d820fc57b9fbc13b94cd3bbc3ec0f && git checkout -B drift-repro ae16687ad430f4f9870ea5ba2bc9b63d6f41fc31 && git merge --no-ff 2c75635eb43d820fc57b9fbc13b94cd3bbc3ec0f
node scripts/docs-audit/affected-docs.mjs --json ae16687ad430f4f9870ea5ba2bc9b63d6f41fc31
|
Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WGufziVeBj5ENSWqsDTaYe
Contract reviewServed-tier: Head note. The brief named Inputs read: card #27155 body and all five comments (claim 6465227713, amendments 6465299594 / 6465901449 / 6466295596, os-dev-report 6467838432); ruling 6464210455 on #27032; #26804 (17b5152) and #24692; #27159 with scope note 6465248799 (edited) and #27153 with seat note 6465263085 (edited); ADR-0087 and ADR-0050 on ① Derived judgments1. Refusals and prescriptions — hold. 2. ADR-0087 disposition — true in code and pinned. D2 3. The kept keys — true, and no sentence overclaims. 4. ui breakage — the form-view surfaces are closed; the remaining carriers are the 5. Tests — re-pinned, nothing weakened. ui: 6. Declarations. 7. Gates (check-runs on ② Semver level
③ Boundary flags
Implemented-by: VERDICT: PASS Posted 2026-10-28T11:45Z · an isolated subagent of the reviewing session; one GitHub write (this comment), no MCP writes. |
维护者速读 (席位终稿)
席位意见:接受。契约复核 PASS(6468131018),确认:各个入口都拒绝、迁移方法只指向有效写法、已存行在读取时转换、保留的三个键确实还有 React 组件在读。渲染器那一半( 席位核对 · ACCEPT ·
|
Requested by Yibo Wang · project thread
Fixes #27155
Ruling-ref: 6464210455
Refs #27153
Clause-②: no (narrowing)
Metadata-protocol: narrowed
Skills-docs: follow-up owed — #27235 (hotcrm src/sales/views/lead.view.ts)
维护者速读
type只表示版式,可选simple(默认)、tabbed、wizard。split、drawer、modal退役,写了会被拒并附改法。只服务分栏表单的pane、splitSize、splitResizable一起退役。Studio 新建视图不再提供这三个值。sys_metadata行在读取时自动转换,os migrate meta --from 17改写源码。本仓只有 showcase 用到,已改写;hotcrm 的lead.view.ts由 hotcrm 席位跟进。回滚就是 revert 本 PR。packages/spec/src/ui/view.zod.ts,FORM_VIEW_TYPE_RETIRED的三条改法文案和type枚举;②packages/spec/src/conversions/registry.ts,formViewPresentationTypesRemoved的apply;③ui/packages/app-shell/src/views/metadata-admin/package-schema.ts,modal改为simple。pnpm --filter @objectstack/spec exec vitest run --project repo src/ui/form-view-type-layout-retirement.test.ts,预期 31 个测试全部通过。What changes
Spec (
@objectstack/spec)FormViewSchema.typeissimple | tabbed | wizard, still defaulting tosimple. It is built withenumWithRetiredValues, sosplit,drawerandmodalare refused by name, each with its own prescription. The prescriptions name live replacements only:split→tabbedor thesimpledefault, withsubformsfor editing child records beside the parent. Opening a record beside its list is the reader's Display-menu preference.drawer/modal→ the caller's open mode: the list'snavigation.mode, the console's New/Edit dialogs (sized bymodalSize), or an actiontype: 'modal'opening a page.FormSectionSchema.pane(and the legacygroups[].pane),FormViewSchema.splitSizeandFormViewSchema.splitResizableareretiredKey()tombstones, refused on every layout. The superRefine check that refusedpaneoff a split form is gone, because the tombstone refuses it everywhere.splitDirection,drawerSide,drawerWidthandmodalSize. See Acceptance notes.spec-property-retirement, value-level route plus key tombstones):form-view-presentation-types-removed(retiredFromLoadPath: true,retiredAfter: '18.2.0', MAJOR_18 order 78). It deletes a retiredtype, so the form lands onsimple, and stripssplitSize,splitResizableand every section's or group'spane. It covers a view container'sformandformViews.*, a form view item'sconfig, and a flattened form overlay, both in stored rows and in existing sources. Its fixture has 9 notices.ui-form-view-type-layout-only(itsconversionIdsnames the conversion), plus a STEP18_RATIONALE fragment.RETIRED_KEYS_BY_MAJORrows:ui/FormSection:pane,ui/FormView:splitSize,ui/FormView:splitResizable.liveness/view.json):splitSizeandsplitResizablearedeadwith REMOVED notes; thetyperow is noted NARROWED;splitDirection,drawerSideanddrawerWidthare noted inert on a form view; thesectionsnote records thepaneremoval.authorable-surface/ui.json(three[RETIRED]rows),content/docs/references/**,liveness/state-counts/view.md.api-surface,react-blocks.mdandskills/**are byte-identical (check:react-blocksandcheck:skill-refsare in sync).content/docs/ui/views.mdxdrops the three rows from the Form Types table and adds a paragraph on where a form opens.protocol/objectui/layout-dsl.mdxdrops thepanemention.Showcase (
examples/app-showcase, private)task.view.ts,formViews.splitis nowtype: 'tabbed'with its panes removed, andformViews.quickis nowtype: 'simple'. The default list declaresnavigation: { mode: 'drawer' }to show the open mode where it now lives.coverage.tshasFORM_VIEW_TYPES = ['simple', 'tabbed', 'wizard']. Comments are updated intranslations/index.tsandnew-project-wizard.page.ts.packages/lint/src/showcase-shape.fixtures.ts, test-only, not shipped) follows, with a header note on the protocol-forced edit.Studio (
@object-ui/app-shell): a defect this PR would otherwise createThe precedent is #26804, which fixed its own Studio inspector in the same PR. Claim amendments 2 and 3 cover this.
metadata-admin/anchors.ts: the New View form'sformTypepicker offerssimple | tabbed | wizard. It offered six values, and the three retired ones would now build a body the server refuses at save.metadata-admin/default-schemas.ts: the viewtypeenum drops the same three values.metadata-admin/package-schema.ts:getPackageForm()returnstype: 'simple'. It returnedtype: 'modal', a spec-typed literal that failstsc(TS2322) after the narrowing.SectionedSchemaFormreads onlytabbed, so the render is unchanged.PackageFormDialogis what opens it as a dialog.view-create-body.test.ts: the three layouts are accepted; a new case shows each retired type refused atconfig.type.formSectionGroupReference-7051.test.tsx:panebesidegroupand the three retired types are refused.form-spec.containers.test.tsxandFormPage.viewSpec.test.ts:paneleaves the "was undeclarable" literals, and a@ts-expect-errorpins it as refused.Why
ADR-0050 was Accepted by ruling 6464210455 on #27032 (letter A′, maintainer 「其他同意」).
typeis the form's layout.drawerandmodaldescribed where a form is opened, which the caller already models.splitwas a list-beside-record view mode, not a layout. The ruling mappedsplitto the list'snavigation.mode: 'split', but #26804 (17b5152) retired that the day before and made the side-by-side pane a reader's preference. Following the seat's ruling, the prescriptions apply the ruling's intent to the current tree and name live values only.Tests
packages/spec/src/ui/form-view-type-layout-retirement.test.ts(31 tests,repoproject, added tovitest.repo-tests.json):invalid_valueattype, plus the prescription's first sentence and migrate sentence. The doors areFormViewSchema,view.form,view.formViews.*, a ViewItem form record and the flattened form overlay;defineStackrefuses withSTACK_SCHEMA_INVALID/ 422 atviews.0.formViews.quick.type;paneis refused on every layout, insectionsand ingroups;splitSizeandsplitResizableare refused too;@ts-expect-errorchecks at the authoring site;task.view.tsin the tree; the walk named it, and I removed the copy.view.test.ts: thepaneblock now pins the tombstone;view-form-features-root.test.ts: tabbed/wizard replace split;section-group-reference.test.ts;view-union-diagnostics.test.ts: three form types, plus a new case where a retired type settles nothing on its own andviewKindstill does;view-metadata-schema.test.ts: reads the vocabulary through the keptsplitDirection;retired-key-removal-version.pin.test.ts: JOIN row.objectstack buildof the showcase withformViews.quickchanged totype: 'modal'(a temporary edit, restored with a trap) exits 2. The refusal sits atformViews.quick.typeand namesos migrate meta --from 17. The unmodified showcase builds with exit 0.Acceptance notes
splitDirection,drawerSideanddrawerWidthstay declared because the ReactObjectFormblock contract (react-blocks.ts) takes itsdataPropsfromFormViewSchema. Tombstoning them would regenerateskills/objectstack-ui/references/react-blocks.mdand make this PR Tier H. They are ui(plugin-form):ObjectFormdrops thesplit/drawer/modalbranches andSplitFormretires; showcasetaskviews re-spelled (ADR-0050 cutover, renderer half of #27155) #27159's, together with the renderer branches (ObjectForm.tsx,ModalForm.tsx,SplitForm), theobject-formformTypeincomponent.zod.ts, and the block-contract keys.modalSizestays because the console's record dialog reads it on every layout.examples/app-showcase/src/ui/views/task.view.ts:formViews.split(split) andformViews.quick(drawer). The lint package's frozen copy of that file repeats them.pane, in the samesplitform view.modalform views and 0splitSize/splitResizableauthorings.package-schema.ts,modal) and 2 Studio enum lists offering the three values.src/sales/views/lead.view.ts(L747, L796, L839 at hotcrm 6c52f22), owed to the hotcrm seat per the Skills-docs line, filed as hotcrm: lead.view.ts authors form views with the retired types split / drawer / modal — re-spell to layouts when hotcrm takes the spec release that carries #27229 #27235.selectViewMetadataBranchreads its form vocabulary offFormViewSchema.type, so a bare{ type: 'modal' }body now settles no branch, as an unknown type does. WithviewKind: 'form'it still reaches the form overlay, whose parse names the prescription. This is diagnostic routing only, and it is pinned.skills/**edit, so the PR is not Tier H.docs/adr/**is untouched.Verification
Head:
edd4570f5. The final-head gate union and full dogfood ran oncd275780d. The last commit (edd4570f5) changes two lines in one ui test file, and the ratchet families plus plugin-formtype-checkwere re-run on it (listed under Derived gates).Type-checks and build
Each was run separately, with its exit code read before any pipe:
pnpm build --concurrency=2(whole workspace, under os-verify-lock):VERDICT command-exit 0, 116/116 tasks. The first two runs exposed thepackage-schema.tsTS2322 and the console test literals; both are fixed in this PR.pnpm --filter @objectstack/spec typecheck(tsc, scripts and the test layer): exit 0.check:test-typecheckis OK, with 132 pinned signatures held.type-checkfor@object-ui/types,@object-ui/plugin-form,@object-ui/app-shell(includingtsconfig.test.json) and@object-ui/console: exit 0 each. plugin-form was re-run onedd4570f5: exit 0.pnpm --filter @objectstack/example-showcase typecheck: exit 0.pnpm --filter @objectstack/example-showcase build: exit 0. WithformViews.quickchanged totype: 'modal': exit 2, with aninvalid_valueatformViews.quick.typewhose message is the prescription, ending in theos migrate meta --from 17sentence.check:react-blocks(1 generated file in sync) andcheck:skill-refs(9 generated files in sync):react-blocks.mdandskills/**are unchanged.Tests
@objectstack/specpnpm test(local project): 740 files, 22234 passed and 1 failed. The failure wasview-metadata-schema.test.ts, which read the vocabulary throughsplitSize; I re-pointed it to the keptsplitDirection, and the re-run passed 50/50.@objectstack/specpnpm test:repo: 82 files, 1355 tests passed.task.view.tsplaced in the tree, the absence walk names it.@objectstack/lintvalidate-translation-referencesandvalidate-translatable-sections: 2 files, 252 tests passed.@objectstack/example-showcasetest: 41 files, 505 tests passed.ui/: every test file that reads a spec view or form schema (371 files, chosen by grep forFormViewSchema|FormSectionSchema|ViewItemSchema|ViewSchema|ViewMetadataSchema|defineStack|FormView|FormSection). 370 passed and 1 skipped; 7978 tests passed and 9 skipped;VERDICT command-exit 0.pnpm --dir ui exec vitest run scripts/: 175 files passed and 2 skipped; 5019 tests passed.Derived gates
node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstackderived 112 commands oncd275780d. Each ran witheval "$cmd" > log 2>&1; status=$?, and all 112 recordedexit 0.dispatch-gates --ran:✓ 112 derived famil(ies) accounted for — 112 run, 0 NOT-MEASURED (a DERIVED zero — all 112 recorded an exit code and none of them is 3).pnpm buildall 11 exited 0, and the final union above includes them.edd4570f5, all exit 0:check:type-check-debt,check:type-check-coverage,check:nul-bytes,check:test-source-alias,check:undeclared-dep-imports,check-comment-mask-adoption.mjsandcheck:issue-citations.formSectionGroupReference-7051.test.tsxcarries the same 18 warnings as at base.Full dogfood
pnpm --filter @objectstack/dogfood testunder os-verify-lock, oncd275780d, after a whole-workspace build:VERDICT command-exit 0.Human Minimum
packages/specholds no runtime logic.pnpm lintpasses.main, one pull request.packages/spectouched: its generated artifacts are regenerated and committed.content/docs/references/,packages/*/CHANGELOG.mdorcontent/docs/releases/.🤖 Generated with Claude Code
https://claude.ai/code/session_01WGufziVeBj5ENSWqsDTaYe