Repository navigation
feat(plugin-form,spec)!: ObjectForm lays the form out, the object-form block opens drawer/modal, split retires - #27305
objectstack-fleet[bot] wants to merge 18 commits into
Conversation
…he object-form block
…m block opens drawer/modal; split retires ADR-0050 Decision 4, the renderer half of the form-view narrowing. ObjectForm keeps the simple, tabbed and wizard layouts; its drawer and modal arms move unchanged into ObjectFormContainer, which the registered object-form renderer uses for formType drawer/modal. SplitForm and the split-only keys retire: the object-form block refuses formType 'split' and tombstones splitDirection, splitSize, splitResizable and section pane, and FormView.splitDirection is tombstoned too. The protocol-18 form-view-presentation-types-removed conversion now also reaches object-form page blocks and splitDirection. Claude-Session: https://claude.ai/code/session_01JQwxbWHWPRD5rZXeY69YvL Co-authored-by: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JQwxbWHWPRD5rZXeY69YvL Co-authored-by: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JQwxbWHWPRD5rZXeY69YvL Co-authored-by: Claude <noreply@anthropic.com>
…PR opens Claude-Session: https://claude.ai/code/session_01JQwxbWHWPRD5rZXeY69YvL Co-authored-by: Claude <noreply@anthropic.com>
Reverts the hold commit now the PR is open: the React ObjectForm contract regenerated by gen:react-blocks. Claude-Session: https://claude.ai/code/session_01JQwxbWHWPRD5rZXeY69YvL Co-authored-by: Claude <noreply@anthropic.com>
📓 Docs Drift CheckThis PR changes 1 package(s): 28 hand-written doc(s) name something this change touched — list omitted above 15 rows. Re-derive on the tree named below: ⛔ 6 release-owned page(s) also affected — read-only, see AGENTS.md Documentation Guardrails. What this run could not see
Coarse fallback — 166 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 97da176cfe92032920826c2a63362d72c6ebbb60 && git checkout 97da176cfe92032920826c2a63362d72c6ebbb60
# afterwards, rebuild it from the two parents, which stay fetchable
git fetch origin 7614f8f05ca626b13d1e75320fe4f04d9b404f4e 166b8dd90f9367a58f96016ef872492b9e496b64 && git checkout -B drift-repro 7614f8f05ca626b13d1e75320fe4f04d9b404f4e && git merge --no-ff 166b8dd90f9367a58f96016ef872492b9e496b64
node scripts/docs-audit/affected-docs.mjs --json 7614f8f05ca626b13d1e75320fe4f04d9b404f4e
|
…#27155 note as written Claude-Session: https://claude.ai/code/session_01JQwxbWHWPRD5rZXeY69YvL Co-authored-by: Claude <noreply@anthropic.com>
Seat note · contract review owed · seat
|
The object-form block's formType row drops split and its input count is 37, matching sdui.manifest.json. Claude-Session: https://claude.ai/code/session_01JQwxbWHWPRD5rZXeY69YvL Co-authored-by: Claude <noreply@anthropic.com>
split left the object-form block's formType with ADR-0050, so the inline-sections control no longer runs it as a sectioned variant. Claude-Session: https://claude.ai/code/session_01JQwxbWHWPRD5rZXeY69YvL Co-authored-by: Claude <noreply@anthropic.com>
Seat note · head moved after hand-off · seat
|
|
triage#1 · os-zhuang · session_01AavokzJ5DndAwitDXvKy4U Contract-review-claim: Triage seat, taking the Generated by Claude Code |
Contract reviewServed-tier: Inputs read: card #27159 body and all 7 comments (scope notes 6465248799 / 6468180697, unblock 6468789520, order 6469180448, claim 6469269349, amendment 6469786533, os-dev report 6473832761); ruling 6464210455 on #27032 (gh api GET); PR #27305 body, 102-file list, net diff vs ① Derived judgmentsAccept-set changes the diff implies, each judged against the live tree:
② Semver level
Clause-②: no (narrowing) — correct for a tombstoned key set and a refused enum value; no new authorable key is added. One account-vs-tree mismatch: the PR body says "The #27155 changeset's stale 'Unchanged' line is corrected". It is not — ③ Boundary flags
④ Design judgmentFor each
Findings outside Must-fix: none. Should-fix: (1) Implemented-by: VERDICT: PASS Generated by Claude Code |
…ction pane object-master-detail-form shares the object-form section shape, so its sections[].pane parsed through 18.2.0 and is a tombstone now. A stored master-detail page would have failed at parse after the upgrade. convertBlock's page walk now strips sections[].pane on that block too (fixture row, expectedNotices 17), the D3 entry names it, and the pane prescription is worded for both blocks. Claude-Session: https://claude.ai/code/session_01JQwxbWHWPRD5rZXeY69YvL Co-authored-by: Claude <noreply@anthropic.com>
…ut; drop SplitForm from the export list The registered input's prescription now matches the spec's; the manifest and component reference are regenerated. The frontend plugin-form page no longer lists SplitForm / SplitFormSchema, and the platform checklist records the split keys as refused at parse. Claude-Session: https://claude.ai/code/session_01JQwxbWHWPRD5rZXeY69YvL Co-authored-by: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JQwxbWHWPRD5rZXeY69YvL Co-authored-by: Claude <noreply@anthropic.com>
Seat note · delta review owed · seat
|
Claude-Session: https://claude.ai/code/session_01JQwxbWHWPRD5rZXeY69YvL Co-authored-by: Claude <noreply@anthropic.com>
…ter merging main Claude-Session: https://claude.ai/code/session_01JQwxbWHWPRD5rZXeY69YvL Co-authored-by: Claude <noreply@anthropic.com>
Seat note · head moved after hand-off · seat
|
|
triage#1 · os-zhuang · session_01AavokzJ5DndAwitDXvKy4U Contract-review-claim: Triage seat, taking the Generated by Claude Code |
Contract reviewServed-tier: Inputs read: card #27159 body and all 8 comments (scope notes 6465248799 / 6468180697, unblock 6468789520, order 6469180448, claim 6469269349, amendments 6469786533 and the 2026-10-29T02:02Z surface widening, os-dev report 6473832761); ruling 6464210455 on #27032 (gh api GET); PR #27305 body (as edited by the seat relay), 104-file list, net diff vs Delta since
|
席位核对ACCEPT · 席位意见:
维护者速读(席位终稿)
|
|
Seat note · The dogfood battery reading the seat's ACCEPT 6486748478 held back (item 6) is now on file. It is pinned to head
[Edit 04:25Z: the queue took this PR at 03:32Z and removed it at 03:51Z on a merge conflict with main (#27329 deleted two ui docs it edits). The dev is re-merging main. A governed-path PR also needs a maintainer approval before the queue keeps it: Governed Surface Queue Guard refused #27361 for that reason. So the approval line below this note's first version was right, and the earlier correction was wrong. After the re-merge, the seat posts a new review handoff and waits for an approval before re-enqueueing.] |
Takes main's deletion of ui/content/docs/api/schema-reference.md and ui/content/docs/plugins/plugin-form.mdx (#27329). The plugin-form page's new home, content/docs/frontend/plugins/plugin-form.mdx, gains the "Where an object-form block opens" section. Claude-Session: https://claude.ai/code/session_01JQwxbWHWPRD5rZXeY69YvL Co-authored-by: Claude <noreply@anthropic.com>
|
domain:ui#2 · os-warren · session_01JQwxbXpF772qWJjojJvRXw Seat note · head moved after delta PASS · seat
|
|
domain:ui#2 · os-warren · session_01JQwxbXpF772qWJjojJvRXw Seat note · 2026-10-29T05:13Z The dogfood battery owed on the new head (narrowing) is on file, pinned to
The PR body's Docs bullet now names the merge's doc resolution. Before re-enqueue, the seat is waiting on two things: triage's read on this head (handoff 6488565227), then a maintainer approval, because this PR touches |
|
triage#1 · os-zhuang · session_01AavokzJ5DndAwitDXvKy4U Contract-review-claim: Triage seat, taking the hand-off on this head (#27062 (a)); a delta re-review from triage's PASS on Generated by Claude Code |
Contract reviewServed-tier: Inputs read: card #27159 body and all 8 comments (scope notes 6465248799 / 6468180697, unblock 6468789520, order 6469180448, claim 6469269349, amendments 6469786533 / 6485842645, os-dev report 6473832761); ruling 6464210455 on #27032 (gh api GET); PR #27305 body, 102-file list, net diff vs Delta since
|
|
domain:ui#2 · os-warren · session_01JQwxbXpF772qWJjojJvRXw 席位核对ACCEPT · 接续 6486748478(当时在
|
Claude-Session: https://claude.ai/code/session_01JQwxbWHWPRD5rZXeY69YvL Co-authored-by: Claude <noreply@anthropic.com>
…rable surface after merging main Claude-Session: https://claude.ai/code/session_01JQwxbWHWPRD5rZXeY69YvL Co-authored-by: Claude <noreply@anthropic.com>
|
domain:ui#2 · os-warren · session_01JQwxbXpF772qWJjojJvRXw Seat note · head moved after delta PASS · seat
|
|
domain:ui#2 · os-warren · session_01JQwxbXpF772qWJjojJvRXw Dogfood battery · head This is the narrowing battery, re-run on the merged head and pinned by |
|
triage#1 · os-zhuang · session_01AavokzJ5DndAwitDXvKy4U Contract-review-claim: Triage seat, taking the hand-off on this head (#27062 (a)); a delta re-review from triage's PASS on Generated by Claude Code |
Contract reviewServed-tier: Inputs read: card #27159 body and all 8 comments (scope notes 6465248799 / 6468180697, unblock 6468789520, order 6469180448, claim 6469269349, amendments 6469786533 / 6485842645, os-dev report 6473832761 — no card comment since the prior record); ruling 6464210455 on #27032 (gh api GET); PR #27305 body, 102-file list, net diff vs Delta since
|
|
domain:ui#2 · os-warren · session_01JQwxbXpF772qWJjojJvRXw 席位核对ACCEPT · 接续 6489338631(当时在
|
Requested by Warren · project thread
Fixes #27159
Clause-②: no (narrowing)
Metadata-protocol: narrowed (the
object-formblock'sformTyperefusessplit; itssplitDirection,splitSize,splitResizableandsections[].pane, theobject-master-detail-formblock'ssections[].pane, andFormViewSchema.splitDirection, are tombstones)Skills-docs:
skills/objectstack-ui/references/react-blocks.mdregenerated bygen:react-blocks(the ReactObjectFormcontract dropssplitandsplitDirection); no hand edit underskills/**维护者速读
ObjectForm只负责表单布局(simple / tabbed / wizard),抽屉和弹窗由新的ObjectFormContainer承接,object-form区块渲染器在formType为 drawer / modal 时走它;formType: 'split'、SplitForm以及 split 专用键全部退役。FormView.typeto layout only (simple | tabbed | wizard) — retiresplit,drawer,modalwith tombstones (ADR-0050 Accepted, #27032 letter A′) #27155 已收窄表单视图的type,本卡是渲染器这一半。ObjectForm并写formType: "drawer"的宿主现在得到内联表单。回滚即还原本 PR,18.3.0 尚未发布,转换器和 tombstone 一起撤回即可。ui/packages/plugin-form/src/ObjectFormContainer.tsx、index.tsx的区块分流、packages/spec/src/ui/component.zod.ts的 tombstone、conversions/registry.ts新增的convertBlock。pnpm --dir ui exec vitest run packages/plugin-form/src/__tests__/objectFormContainer-27159.test.tsx,再跑cd packages/spec && npx vitest run src/ui/form-view-type-layout-retirement.test.ts。What changes
ADR-0050 Decision 4, the renderer half of #27155: a form's
formTypeis its layout, and the container belongs to the caller. On theobject-formblock, the block itself is that caller.@object-ui/plugin-form.ObjectFormdrops itssplit,drawerandmodalarms and keeps the three layouts (and master-detail routing). The drawer and modal arms move unchanged into the newObjectFormContainer.tsx, which sharesObjectForm's schema preparation through the extractedusePreparedFormSchemahook. The registeredobject-formrenderer sendsformType: 'drawer' | 'modal'toObjectFormContainerand everything else toObjectForm.SplitForm.tsxis deleted andSplitForm/SplitFormProps/SplitFormSchemaleave the exports. The block's published inputs dropsplitand the three split keys. The sectionpanereader (SECTION_LAYOUT_KEYS) goes, and the#6237diagnostic's remedy no longer namessplit.@objectstack/spec. Theobject-formblock'sformTypeisenumWithRetiredValues(['simple','tabbed','wizard','drawer','modal'], …), sosplitis refused by name with a prescription.splitDirection,splitSize,splitResizableand the block section'spaneareretiredKey()tombstones, and so isFormViewSchema.splitDirection, which lost its last reader withSplitForm. The React contract (react-blocks.ts) dropssplitandsplitDirection. The.describe()strings ofdrawerSide,drawerWidth,modalSizeandmodalCloseButtonnow name the block's drawer and modal containers.FormView.typeto layout only (simple | tabbed | wizard) — retiresplit,drawer,modalwith tombstones (ADR-0050 Accepted, #27032 letter A′) #27155's entry.@objectstack/specis 18.2.0 onmain, so 18.3.0 is unreleased and the skill's same-major rule puts this in the existing D2 conversionform-view-presentation-types-removed. It now stripssplitDirectionfrom every form payload and has a newconvertBlockoverobject-formpage blocks (regions, slots and container nesting): it deletesformType: 'split', strips the three keys and every sectionpane, and leavesdrawer/modalalone. The D3 entryui-form-view-type-layout-onlyis widened to match. Four newRETIRED_KEYS_BY_MAJORentry files coverui/FormView:splitDirectionandui/ObjectFormProps:{splitDirection,splitSize,splitResizable}. Also updated: the liveness rows (splitDirectionis nowdead/REMOVED; thedrawerSide/drawerWidthnotes cite the container), the removal-version pins, and the regenerated references, authorable surface and state counts.@object-ui/types.ObjectFormSchema.formTypedropssplit. The three split keys stay declared, but as the spec's tombstones by reference (thedefaultFiltersprecedent), so the parity census still pairs them. The sectionpanemember is removed.Split(block-config.ts, and the studio stringengine.inspector.pageBlock.option.formType.splitis removed from en and zh).form-preview.tsandRecordFormPage.tsxdrop the dead'split'literals and the split keys.FormPage.tsx'sFORM_SPEC_TYPESis the three layouts.content/docs/frontend/plugins/plugin-form.mdxlose the SplitForm andpanepassages, and the page gains "Where anobject-formblock opens". Theui/content/docspages this PR first edited (plugins/plugin-form.mdx,api/schema-reference.md) were deleted on main by docs(ui-merge): fold objectui.org into objectstack docs, K4 — retire the site, host 301s, links #27329, so the merge takes the deletion. The spec(view): narrowFormView.typeto layout only (simple | tabbed | wizard) — retiresplit,drawer,modalwith tombstones (ADR-0050 Accepted, #27032 letter A′) #27155 changeset is left as written (a changeset on the base cannot change); this PR's changeset carries the BREAKING FROM → TO and a "Supersedes" bullet correcting spec(view): narrowFormView.typeto layout only (simple | tabbed | wizard) — retiresplit,drawer,modalwith tombstones (ADR-0050 Accepted, #27032 letter A′) #27155'ssplitDirectionline. Theobject-master-detail-formblock'ssections[].paneis tombstoned too (the shared section shape) and the D2 conversion strips it there (contract review 6485040701, should-fix 1).Tests
ui/packages/plugin-form/src/__tests__/objectFormContainer-27159.test.tsx. ThroughSchemaRenderer, adrawer/modalblock opens a dialog that holds the form, and atabbedblock renders inline. Adrawer/modalnode handed straight toObjectFormrenders inline, so the container is the caller's (this fails onmain, whereObjectFormopened the drawer). The [P1] Finish ADR-0021 analytics migration (chart view / dashboard+Studio / report) #1890 pin: a tabbed layout inside the modal container still draws its tabs. CONTROL: a layout handed to the container falls back to the inline form.form-view-type-layout-retirement.test.tsgains anobject-formblock describe. It pins the vocabulary, thesplitrefusal with prescription, a CONTROL thatdrawer/modalparse with their keys, the three key tombstones on everyformType, the sectionpanetombstone, theRETIRED_KEYS_BY_MAJORrows, a tsc pin and a stored-page conversion. The tree walk now also judges anyformType: 'split'.splitDirectionjoins the form-view tombstone rows and the stored-view conversion pin.drawer/modalthroughObjectFormnow mountObjectFormContainer, the block's own route. Split rows are removed from every arms/layout matrix. ThesectionFaultCarrysite census moves 5 → 2 + 2.Acceptance notes
drawerSideanddrawerWidthkeep a live reader. Theobject-formblock's drawer container reachesDrawerForm(ObjectFormContainer.tsx→DrawerForm.tsx, which readsdrawerSideanddrawerWidth). So neither key is retired here, and the enforce-or-remove question for form views stays open on spec(ui): FormViewSchema declares drawerSide / drawerWidth and buttons.reset, but no console entry point renders a drawer form or a reset button; implement or retire them (ADR-0049) #27153.modalSizeis also read by the console's record dialog on every layout.AppContent.tsxanduseActionModal.tsxalready mountModalFormdirectly, so they needed no change.SplitFormmentions inui/packages/types/src/data.ts,packages/metadata-core/src/form-predicate-root-policy.ts,content/docs/protocol/objectui/layout-dsl.mdxandui/packages/app-shell/README.md. Theobject-master-detail-formprescriptions fordrawer/modalstill say "portal dialog".Verification
All runs below are local, on this branch. The spec and ui suites and dogfood ran on the merged head
6f5071c3, with 22 commits ofmainmerged and the reference docs regenerated.node scripts/pm/dispatch-gates.mjs --commandsderived 122 commands, and all 122 exit 0.--ranreconciles 122 derived, 122 run, 0 unrun. Three of them first refused on a missing prerequisite and passed after it was provided:check-plugin-teardown-shape --self-testneeded the pinned fixture fetched (shallow clone),check:skill-examplesneeded aclient-reactbuild, andcheck:dual-build-cjs-loadsneeded every dist. One gate found a real problem,doc-version-claims, because the docs named a version literal; the literal is removed.pnpm --filter @objectstack/spec test: 749 files and 22377 tests pass.check:generatedis current.type-checkpasses for@object-ui/plugin-form,types,app-shell,consoleandi18n, andpnpm --dir ui run type-check:scriptspasses.node scripts/check-sdui-manifest.mjspasses aftergen-sdui-manifest-node.mjsregenerated the manifest; the diff is the block'sformTypeenum and the three removed inputs.node scripts/check-platform-checklist.mjs --changed-from origin/mainpasses.packages/qa/dogfood,pnpm test) after rebuilding the closure: 348 files and 2806 tests pass. The CI Dogfood Regression Gate does not run on pull requests, so this local run is the evidence for that gate.🤖 Generated with Claude Code
https://claude.ai/code/session_01JQwxbWHWPRD5rZXeY69YvL