Repository navigation
Commit e3782d2
feat(types)!: an authored
Part of #10859
Clause-②: yes
`Clause-②: yes`, copied from the PM claim `5920453930`:
`@object-ui/types`' authoring faces narrow (a flat `object-form` node
that parsed is refused) and widen (a spec-shaped bag node that was
refused parses). This is objectui's narrowing-as-`minor` rule with a
**BREAKING (authoring)** banner in the changeset, as batches 1 to 3 and
the answer's step 2 state.
Batch 4 of objectui#10859. It executes the seat's flat-arm answer at PR
objectui#11248's ACCEPT (`5917261346`) for ONE block, `object-form`: "A
governs, by inheritance" from objectui#10872's triage answer A
(`5906817482`), "The `properties` bag is the contract". The card stays
open for the rest of the flat-arm fork (`object-map`, `object-gantt`),
the designer six and the (ii) / (iii) keys.
## What changed
- `packages/types/src/zod/objectql.zod.ts`: new `ObjectFormBlockSchema`,
the batch-2/3 construct. It is `BaseSchema`, plus the `object-form`
literal, plus `NODE_ENVELOPE`, plus `properties` =
`propsBag('object-form',
stripImportedDefaults(SpecObjectFormPropsSchema))`: the shared helper
and the installed 17.5.0 row by reference, with no copy. Beside it:
- `dataSource`, the spec's `ElementDataSourceSchema` by reference (the
registration is `elementDataSourceBlock`-wrapped; the flat mirror has
declared it since objectui#11070);
- one `aliasKeyRefusal` per member of the row, keyed by the row's own
key set read off the crossed row, so each prop written flat is refused
on both faces with `Did you mean KEY → properties.KEY?` and one
prescription string that shows the whole bag document;
- the five runtime slots `ObjectForm` reads off the node (`onSuccess`,
`onCancel`, `onError`, `onOpenChange`, `onStepChange`), declared exactly
as on the flat mirror;
- `body` / `children` refused with the flat mirror's objectui#9256
string.
- The arm joins `ObjectQLPublicBlockComponentSchema`. `ObjectFormSchema`
(the flat mirror) leaves `ObjectQLComponentSchema`, stays exported, and
stays paired with its TypeScript twin in the parity census.
- `packages/types/src/objectql.ts`: the TypeScript `ObjectFormSchema` is
**re-declared, not retired**. Its members are unchanged; its docblock
now says what it is: the node as `ObjectForm` reads it after
`SchemaRenderer` hoists `properties`, and as code composes it. The
TypeScript union's docblock names the zod union's new count.
- `packages/types/src/zod/form.zod.ts`: the `form` node's `mode` refusal
taught a flat `object-form` document. Its prescription now writes the
bag.
- `packages/types/src/zod/index.zod.ts` (one barrel export) and
`packages/types/src/zod/README.md` (the ObjectQL public-block group
lists the arm).
- objectui's authored flat producers, rewritten to the bag (census
below): the root `README.md`, `content/docs/api/schema-reference.md`,
`content/docs/guide/building-crud-app.md`,
`content/docs/guide/objectos-integration.mdx`,
`content/docs/plugins/plugin-form.mdx`, both schema-catalog
`object-form` fixtures, and `packages/plugin-form/README.md`.
- New pins:
`packages/types/src/__tests__/object-form-properties-bag-10859-b4.test.ts`
and
`packages/plugin-form/src/__tests__/objectFormPropertiesBag-10859.test.tsx`.
- Two changesets: `.changeset/10859-object-form-properties-bag.md`
(`@object-ui/types` minor, BREAKING (authoring) banner) and
`.changeset/10859-plugin-form-readme-object-form-bag.md`
(`@object-ui/plugin-form` patch, README only).
**Files beyond the claimed surface**, each forced and named:
- `zod-mirror-parity.test.ts`: the one `EXCLUSIONS` row the new export
forces; no pair moved (`EXPECTED_MIRROR_PAIRS` untouched).
- `imported-defaults-8317.test.ts`: one `IMPORTED` row for the new spec
import.
- `registered-type-arms-10859-b2.test.ts`: its exact
`ObjectQLPublicBlockComponentSchema` literal list gains `object-form`.
- `objectql-union-arms-7363.test.ts`: `ObjectQLComponentSchema` holds 11
arms, not 12, and a row that `object-form` is not among them.
- `public-block-responsive-styles-10872.test.ts`: `object-form` joins
the named `DECLARES_DATA_SOURCE` set (it moved into the public-block
population carrying the binding).
- Fixture triage (respelled, the flat node is now refused):
`strict-face-read-keys-11070.test.ts` (one `BOUND_NODES` row),
`content-channel-e3-residual-9256.test.ts` (the authoring-face reach row
reads the bag; the mirror rows keep the post-hoist spelling),
`object-form-unmirrored-members-6152.test.ts` (details under Acceptance
notes), `guideCrudAppRenders.test.tsx` (reads the guide snippet's bag),
`catalog-gallery-render.test.tsx` (its control uses the entries'
spelling).
## Zone 2: the PM's mechanism assumptions, measured before building
1. **Held (the gate for the batch).** Installed `@objectstack/spec`
17.5.0, and objectstack `origin/main` `75519e1c0a` (spec source run with
`tsx`):
- `ComponentPropsMap` carries an `object-form` row, and it is the
exported `ObjectFormPropsSchema` (same key set at both refs).
- `PageComponentSchema.safeParse({ type: 'object-form', objectName: 'x'
})` refuses: `unrecognized_keys ['objectName']` ("Unrecognized key(s) on
this page component … ADR-0089 D3a"). With `mode` beside it:
`['objectName', 'mode']`.
- The same props in `properties` are accepted, and the row accepts them.
- Control: flat `action:button` `actionType` is refused the same way.
2. **Held, red first.** On base `f16c01e90e`, the showcase wizard node
(objectstack `NewProjectWizardPage`) was refused by `safeValidateSchema`
(`objectName` `invalid_type`, `mode` `invalid_value`) and by the strict
face (the same two, plus `unrecognized_keys ['properties']`). The flat
control was accepted on both faces. The new pin on base, before the arm:
`Tests 58 failed | 7 passed (65)`. The 7 green rows are the lit
controls, the row size check, the content-channel rows and the
flat-mirror row, which all hold on base too.
3. **Settled: re-declared, not retired.** Readers of the TypeScript
twin, measured:
- `ObjectForm` and its five variant forms (the `schema` prop);
- the code composers (`ObjectView`, `RecordFormPage`, `ScreenView`,
`AppContent`, `useActionModal`, `EmbeddableForm`, `MasterDetailForm`,
`ViewPreview`, `StudioDesignSurface`, `ObjectManager`, `FieldDesigner`);
- the object-view `form` slot (`ObjectFormSlotKey`; the zod slot is
`ObjectFormSchema.omit(…).partial()`);
- the TypeScript unions;
- the mirror-parity census pair.
Every one reads the post-hoist or code-composed flat node. None needs
the authored shape, so the twin keeps its members and its publication.
The authored node is typed by `BaseSchema` (index signature) or the
spec's `ObjectFormProps`. The bag arm is unpaired (one `EXCLUSIONS`
row), as batch 2's `MasterDetailFormSchema` split is. Type-level pins:
the bag input equals `ObjectFormProps | undefined`, every row key is a
refused flat member, and the twin stays `type: 'object-form'` with
`objectName: string` and `mode` required, still the `object-form` member
of the TypeScript ObjectQL union.
4. **Census** (classifier: a document or doc example an author writes,
versus code that builds the node or mounts a component with its
post-hoist `schema` prop):
| class | files | action |
|:--|:--|:--|
| authored, rewritten to the bag | root `README.md`,
`schema-reference.md`, `building-crud-app.md`,
`objectos-integration.mdx`, `plugin-form.mdx`,
`object-form-record.json`, `object-form-tabbed-sections.json`,
`packages/plugin-form/README.md` (2 of its 3 nodes), `form.zod.ts` (a
refusal's prescription) | rewritten (9 files) |
| authored, already bag-compatible |
`content/docs/utilities/data-objectstack.mdx` (`{ type, dataSource }`
only) | none |
| authored, governed | `skills/objectui/guides/page-builder.md` ("Form
plugin example") | **listed, not edited** (ruling step 4) |
| authored, held by another PR | `packages/cli/src/commands/validate.ts`
(a hint naming `type: 'object-form'` with `objectName` + `sections`) |
not edited: the file is PR objectui#11069's |
| component mount (post-hoist `schema` prop, no hoist) |
`examples/byo-backend-console/src/App.tsx` (2),
`packages/plugin-form/README.md` (the `WizardForm` mount), the
`@example` blocks of `ObjectForm` / `TabbedForm` / `WizardForm` | kept
flat: rewriting them would break them |
| runtime composers | the eleven listed under item 3 | kept flat (item
5) |
| test fixtures | the triage above; the plugin-form render tests build
flat nodes as code does | respelled only where a face judges them |
This differs from batch 3's count ("13 authored") in two classes: the
two `byo-backend-console` nodes and the two designer nodes are component
mounts and code composers, not authored documents.
5. **Held.** No composed node passes through `safeValidateSchema`.
`SchemaRenderer` runs `@object-ui/core`'s structural `validateSchema`,
and the only non-test callers of the zod faces are `objectui validate` /
`objectui check`. The render pin draws the flat spelling beside the bag.
6. **Not forced.** `REFUSED_AT_TYPE` does not move: `object-form` was
never refused at `type`. PR objectui#11069's files are untouched, and
`git merge-tree` of this head with `origin/main` is clean.
## Tests (the union at head `a32a4470cd` unless marked; heavy runs
through `os-verify-lock.sh`, slot `issue-10859`)
- **Red first** (base `f16c01e90e`, pin present, arm absent): `Tests 58
failed | 7 passed (65)`.
- **Green at `a32a4470cd`:**
- `pnpm exec vitest run packages/types/ packages/cli/`: `Test Files 323
passed (323)`, `Tests 7875 passed (7875)`, VERDICT command-exit 0.
- The render pin, the guide test, the b4 pin and
`examples/schema-catalog/test/`: `Test Files 39 passed (39)`, `Tests
2290 passed (2290)`.
- **Arm-list consumer sweep at `8e741e3fe4`:**
- The files are every tracked test file outside `packages/types` and
`packages/cli` that names `AnyComponentSchema`,
`StrictAnyComponentSchema`, `safeValidateSchema`,
`ObjectQLPublicBlockComponentSchema`, `ObjectQLComponentSchema`,
`ObjectFormBlockSchema`, `nodeOracles`, `KNOWN_SCHEMA_TYPES`,
`propsLevelOf`, `PUBLIC_BLOCKS`, `unmirroredAlias`, `collectArms`,
`getPublicConfigs`, `ComponentPropsMap`, `validateSchema` or
`StrictAuthoringFace`; or references `check-handler-key-read-sites`,
`block-config-schema-parity`, `registry-inputs-spec-parity`,
`strict-authoring-face`, `zod-mirror-parity`, `objectql.zod`,
`index.zod`, `ObjectFormSchema` or `object-form`.
- That is 312 files, run in two chunks: `Test Files 180 passed (180) /
Tests 4016 passed (4016)` and `Test Files 132 passed (132) / Tests 1626
passed (1626)`.
- The only changes since are the changeset text and the render pin's
casts; that pin re-ran green at `a32a4470cd`.
- **Build / type-check:**
- `pnpm --filter @object-ui/types build && pnpm --filter
@object-ui/types type-check`: VERDICT 0, `dist completeness: 1
package(s) complete (138 emitted files verified)`. The pin is in
`tsconfig.test.json`'s program (`--listFilesOnly`).
- `pnpm --filter @object-ui/plugin-form type-check`: exit 0, after
building its dependency closure. Both plugin-form test files are in its
test program.
- **Runtime ablation** (objectstack `scripts/ablation-replace.mjs` WRAP,
plus the script's own EXIT/INT/TERM trap on absolute paths):
- The mutation removed `ObjectFormBlockSchema` from the public-block
union: anchor x1 to x0, blob `03e9d3554ceb` to `5981e32df7dd`.
- Pin + ratchet: `Tests 60 failed | 25 passed (85)`, with "`objectui
validate` refuses 73 registered bare key(s) at `type`; the pin is 72".
Direction: red, as expected.
- Restored: blob == HEAD `03e9d3554ceb`, `git diff HEAD` empty.
- **Type-level reverse validation** (same tool):
- Bag narrowed to `{ objectName? }`: `tsc -p tsconfig.test.json` exit 2,
`TS2344: Type 'false' does not satisfy the constraint 'true'` on the bag
row.
- Flat refusals removed: exit 2 (TS2339 on the three flat-member rows,
TS2344 on the every-row-key row).
- Restored as above.
- **Render** (committed pin, real registry): the bag node fetches
`getObjectSchema('showcase_project')` and draws the three step labels
and the first step's field. The flat spelling draws the same. Control: a
bag naming another object fetches that object and never
`showcase_project`.
## Gates (exit codes read before any pipe)
- exit 0, each with its own verdict line:
- `check:handler-key-reads`: "OK 140 arm(s), 212 registration(s) (138
keyed onto an arm), 56 reachable handler read(s), 56 judged";
- `check:spec-symbols`;
- `check:new-line-citations`: "VERDICT new-cross-file-line-citations: 0
new citation(s)";
- `check:control-bytes`: "OK (scanned 9718 tracked text file(s); skipped
85 binary)"; a self-scan over the 27 changed files gave 0 hits;
- `node scripts/check-changeset-presence.mjs`: "16 source file(s) of 2
released package(s) changed, and this change declares 2 changeset(s)";
- `changeset:check`: "No changeset declares a `major` bump.";
- `check:doc-fences`, `docs:check-links`, `markdown-test-inputs.mjs
--audit` ("107 candidate test files, all adjudicated");
- `check:doc-snippets`: "697 of 697 block(s) judged, 0 failed", after
its scoped build;
- `check:doc-examples`, `check:doc-types`, `check:readme-exports`;
- `check:element-data-source-declaration`, `check:installed-pin-claims`,
`check:test-path-roots`, `check:pending-changeset-literals`,
`check:unreferenced-sources`, `check:esm-specifiers`,
`type-check:coverage`.
- `check:changeset-claims` (report-only): the pending
`.changeset/6152-object-form-unmirrored-members.md` describes the flat
members this change moves into the bag. Its body is not edited. This
PR's changeset names how those members are authored now, so the release
notes read together.
- `check-governed-queue-guard.mjs --test` over the 27 paths: NOT
GOVERNED.
- eslint narrowing: `eslint --no-inline-config --format json` over the
16 changed `.ts` / `.tsx` files gives 0 errors. Warnings equal the base
blobs file for file (43; the two new files carry 0). `eslint.config.js`
sets no `projectService` / `parserOptions.project`, so no untouched
file's verdict can move. The full `pnpm lint` is CI's.
## Acceptance notes
- **The bag follows the spec row, which is not the flat mirror.**
Measured in the pin. The row keeps `objectName` / `mode` optional;
`layout` is `vertical` / `horizontal` only (17.5.0 retired `inline` /
`grid`); `recordId` takes a number (objectui#9511 refuses one on the
flat mirror, and batch 2's `object-master-detail-form` bag already takes
one). The row types `sections` entries as `unknown`, so a section's keys
are unjudged inside the bag (the flat mirror closed them).
- **`buttons` / `defaults` / `subforms` / `groups`** are the spec's
form-VIEW members, not row members, so the bag refuses them.
`object-form-unmirrored-members-6152.test.ts` now says so for the three
objectui#6152 declared: refused in the bag on both faces, still taken by
the object-view `form` slot. The "a section is a closed shape on the
strict face" row reads that slot too.
- **The TypeScript twin does not name `contentLayout` /
`confirmOnDiscard`**, two row members `ModalForm` / `DrawerForm` read;
`BaseSchema`'s index signature types them `any`. This is an observation,
not filed.
- **Governed producer left flat:**
`skills/objectui/guides/page-builder.md` ("Form plugin example",
`os:check`-marked). It still parses as JSON, which is all
`check:skill-examples` asks of a JSON fence, but `objectui validate` now
refuses it. It goes through the governed path.
- **Hint held by PR objectui#11069:**
`packages/cli/src/commands/validate.ts` still suggests `type:
'object-form'` with `objectName` + `sections` flat.
- The `objectos-integration.mdx` fragment also dropped `fieldNames` (no
such key; the row's is `fields`), a node-level adapter and an `onSubmit`
function, none of which the node ever took.
---
_Generated by [Claude
Code](https://claude.ai/code/session_0122Knsowci76D2rBWReCzzZ)_
---------
Co-authored-by: Claude <noreply@anthropic.com>object-form takes its props in the spec's properties bag; the flat spelling is refused by name (objectui#10859, batch 4) (#11291)1 parent 4840168 commit e3782d2
27 files changed
Lines changed: 874 additions & 140 deletions
File tree
- .changeset
- content/docs
- api
- guide
- plugins
- examples/schema-catalog
- src/schemas/plugin-form
- test
- packages
- plugin-form
- src/__tests__
- types/src
- __tests__
- zod
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
326 | 326 | | |
327 | 327 | | |
328 | 328 | | |
329 | | - | |
| 329 | + | |
330 | 330 | | |
331 | 331 | | |
332 | 332 | | |
333 | 333 | | |
334 | 334 | | |
335 | 335 | | |
336 | | - | |
337 | | - | |
| 336 | + | |
| 337 | + | |
| 338 | + | |
338 | 339 | | |
339 | | - | |
340 | | - | |
341 | | - | |
| 340 | + | |
| 341 | + | |
| 342 | + | |
| 343 | + | |
| 344 | + | |
342 | 345 | | |
343 | 346 | | |
344 | 347 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
815 | 815 | | |
816 | 816 | | |
817 | 817 | | |
| 818 | + | |
| 819 | + | |
818 | 820 | | |
819 | 821 | | |
820 | 822 | | |
821 | | - | |
822 | | - | |
823 | | - | |
824 | | - | |
825 | | - | |
826 | | - | |
827 | | - | |
828 | | - | |
829 | | - | |
830 | | - | |
831 | | - | |
832 | | - | |
833 | | - | |
834 | | - | |
835 | | - | |
836 | | - | |
837 | | - | |
838 | | - | |
839 | | - | |
840 | | - | |
841 | | - | |
| 823 | + | |
| 824 | + | |
| 825 | + | |
| 826 | + | |
| 827 | + | |
| 828 | + | |
| 829 | + | |
| 830 | + | |
| 831 | + | |
| 832 | + | |
| 833 | + | |
| 834 | + | |
| 835 | + | |
| 836 | + | |
| 837 | + | |
| 838 | + | |
| 839 | + | |
| 840 | + | |
| 841 | + | |
| 842 | + | |
| 843 | + | |
| 844 | + | |
| 845 | + | |
842 | 846 | | |
843 | 847 | | |
844 | 848 | | |
| |||
851 | 855 | | |
852 | 856 | | |
853 | 857 | | |
854 | | - | |
855 | | - | |
| 858 | + | |
| 859 | + | |
856 | 860 | | |
857 | 861 | | |
858 | 862 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
286 | 286 | | |
287 | 287 | | |
288 | 288 | | |
289 | | - | |
290 | | - | |
291 | | - | |
| 289 | + | |
| 290 | + | |
| 291 | + | |
| 292 | + | |
| 293 | + | |
292 | 294 | | |
293 | 295 | | |
294 | 296 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
539 | 539 | | |
540 | 540 | | |
541 | 541 | | |
542 | | - | |
| 542 | + | |
543 | 543 | | |
544 | 544 | | |
545 | | - | |
| 545 | + | |
| 546 | + | |
| 547 | + | |
| 548 | + | |
546 | 549 | | |
547 | 550 | | |
548 | | - | |
549 | | - | |
550 | | - | |
551 | | - | |
552 | | - | |
553 | | - | |
554 | | - | |
| 551 | + | |
| 552 | + | |
| 553 | + | |
| 554 | + | |
| 555 | + | |
555 | 556 | | |
556 | 557 | | |
557 | 558 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
531 | 531 | | |
532 | 532 | | |
533 | 533 | | |
| 534 | + | |
| 535 | + | |
| 536 | + | |
534 | 537 | | |
535 | 538 | | |
536 | 539 | | |
537 | 540 | | |
538 | | - | |
539 | | - | |
540 | | - | |
541 | | - | |
542 | | - | |
543 | | - | |
544 | | - | |
545 | | - | |
546 | | - | |
547 | | - | |
548 | | - | |
549 | | - | |
550 | | - | |
551 | | - | |
552 | | - | |
553 | | - | |
| 541 | + | |
| 542 | + | |
| 543 | + | |
| 544 | + | |
| 545 | + | |
| 546 | + | |
| 547 | + | |
| 548 | + | |
| 549 | + | |
| 550 | + | |
| 551 | + | |
| 552 | + | |
| 553 | + | |
| 554 | + | |
| 555 | + | |
| 556 | + | |
| 557 | + | |
| 558 | + | |
554 | 559 | | |
555 | 560 | | |
556 | 561 | | |
| |||
Lines changed: 8 additions & 6 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1 | 1 | | |
2 | 2 | | |
3 | | - | |
4 | | - | |
5 | | - | |
6 | | - | |
7 | | - | |
8 | | - | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
9 | 11 | | |
Lines changed: 13 additions & 11 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1 | 1 | | |
2 | 2 | | |
3 | | - | |
4 | | - | |
5 | | - | |
6 | | - | |
7 | | - | |
8 | | - | |
9 | | - | |
10 | | - | |
11 | | - | |
12 | | - | |
13 | | - | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
14 | 16 | | |
Lines changed: 7 additions & 4 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1135 | 1135 | | |
1136 | 1136 | | |
1137 | 1137 | | |
| 1138 | + | |
1138 | 1139 | | |
1139 | 1140 | | |
1140 | | - | |
1141 | | - | |
1142 | | - | |
1143 | | - | |
| 1141 | + | |
| 1142 | + | |
| 1143 | + | |
| 1144 | + | |
| 1145 | + | |
| 1146 | + | |
1144 | 1147 | | |
1145 | 1148 | | |
1146 | 1149 | | |
| |||
0 commit comments