feat(plugins): publish the four GA object-* blocks' authoring surfaces (#4648) - #4901
Merged
Merged
Conversation
Contributor
✅ Console Performance Budget
📦 Bundle Size Report
Size Limits
|
os-steve
marked this pull request as ready for review
August 17, 2026 03:05
os-steve
pushed a commit
that referenced
this pull request
Aug 17, 2026
…ost-adaptation main) Re-points the GA pin bump onto main after the four pre-re-point adaptations landed (#4649 / #4650 / PR #4671 / PR #4901). package.json range lines merged cleanly (no conflicts); pnpm-lock.yaml was REGENERATED rather than hand-merged: main's lockfile was taken verbatim and `pnpm install` re-run with the raised ranges. The resulting lockfile diff vs main touches only the six @objectstack/* packages. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DbRmJD3iPhXjKr6vhd4Qkv
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Part of #4648
Every piece of that card's ruled scope is implemented here, so this is
Part ofrather than a closing keyword for one reason only: the carve-out measures ten keys where the ruling enumerated five (see the flagged delta below), and the card is the right home for that one-line call. Flip it to a closing keyword on review if the delta is accepted as written.Implements the maintainer ruling of 2026-08-16 on that card — option B (declare the keys) with option C's deprecated-alias carve-out. This is the successor step to PR #4671, which adapted the parity gates and forked this item back to the card.
Net effect: on a GA-installed tree the console registry-inputs parity gate goes from 4 failures to 0. Those four were the last of the eight #4671 inherited, so this is the piece #4639's re-point was waiting on.
What changed, and why it is not new capability
All four blocks are long-standing objectui renderers that honoured far more keys than they declared. An author — very often an AI author — who wrote one of the undeclared keys got
unknown-propfromsdui-parseron a key that works, while the designer panel and the generatedsdui-intrinsics.d.tsdenied it existed. Publishing makes the manifest, the.d.ts, the designer and the renderer agree. No renderer behaviour changes.Descriptions are sourced from GA's own
.describe()text plus this repo's props TSDoc, and written to teach authoring — each legacy/canonical pair says which spelling to prefer and what supersedes what.Re-derived measurement (78 keys, confirmed)
Re-derived on this branch from the resolved
ComponentPropsMap[type].shapeunder the GA overlay, not taken from the card:object-formobject-gridobject-master-detail-formobject-metricThe card's 78 / 20 / 34 / 10 / 14 reproduce exactly.
object-form+20 —packages/plugin-form/src/index.tsxrecordId,customFields,initialValues,initialData,readOnly,modalCloseButton,contentLayout,confirmOnDiscard,submitText,cancelText,nextText,prevText,showSubmit,showCancel,showReset,submitBehavior,successMessage,navigateOnSuccess,resetOnSuccess,mobileobject-grid+21 —packages/plugin-grid/src/index.tsx(GRID_QUERY_INPUTS)label,sort,pagination,searchableFields,data,rowHeight,frozenColumns,resizable,reorderableColumns,showColumnTypeIcons,rowColor,conditionalFormatting,grouping,aggregations,selection,rowActions,bulkActions,batchActions,bulkActionDefs,editable,singleClickEdit,navigation,operations,exportOptionsDeclared on the shared const, so the
view:gridalias cannot drift from the block — the invariant that const's own comment states.object-master-detail-form+10 —packages/plugin-form/src/index.tsxrecordId,formType,fields,title,submitText,cancelText,showSubmit,initialValues,initialData,taxRateFieldobject-metric+14 —packages/plugin-dashboard/src/index.tsxdescription,title,filter,colorVariant,variant,format,currency,prefix,suffix,invert,fallbackValue,trend,compareTo,drillDownThe carve-out — 10 keys, cited
Ruled: "object-grid's own
@deprecatedlegacy spellings … are NOT published as new authoring surface — they get reasoned, cited exemptions so a deprecated alias is not hardened." Each gets an entry inUNPUBLISHED_EXEMPTIONSnaming the canonical spelling that IS declared in its place.@deprecatedtag inObjectGridSchemafieldscolumnsis absent"columnsstaticDatadata"dataselectableselection"selectionpageSizepaginationshowSearchsearchableFieldsis absent"searchableFieldsshowPaginationpaginationis absent"paginationdefaultSortsort"sortdefaultFiltersfilter"filterresizableColumnsresizable"resizabletitlelabel"labelThe gate's stated exemption bar is not amended — option B is the arm that needed no amendment, which the ruling says explicitly.
The ruling enumerated five (
fields/staticData/selectable/pageSize/showSearch), carried over from the fork report's list. Re-deriving the class the ruling named — tagged@deprecatedinObjectGridSchemaand declared by GA — measures ten. The five extra (showPagination,defaultSort,defaultFilters,resizableColumns,title) are the same class by the same test, with both authorities agreeing, so they are carved out with the enumerated five rather than published.This is the one place this PR goes beyond the ruling's literal list, and it is deliberately in the reversible direction: trimming back to exactly five is one line each (delete the entry, declare the input), whereas publishing a key and later withdrawing it is a breaking change to published surface. Say the word and it becomes five.
One key sits just outside:
batchActionsis called a "Legacy alias ofbulkActions" in its own TSDoc but is not tagged@deprecated, so by the ruled test it publishes. It is declared, with a description steering authors tobulkActions. Happy to move it if the intended test was prose rather than the tag.Sequencing — and a correction to the assumed blocker
The card and the dispatch both record that "the parity gate's forward direction rejects these keys on rc.6", which is why option B was phased behind the pin bump. Measured, the forward direction never sees them.
coveredisObject.keys(ComponentPropsMap).filter(has inputs), and rc.6 does not carry the four blocks at all — so they are not incovered, and no forward assertion is generated for them. The declarations are simply dormant on rc.6 and fully judged on a GA tree.Consequences, both good:
maingreen today, ahead of the pin, with no gate weakening and no new pin-aware mechanism for the declarations themselves;The carve-out exemptions do need the pin-aware mechanism, because they name keys rc.6 cannot resolve: the ten are added to
GA_PENDING_UNPUBLISHED_KEYS, the set PR #4671 built, soevery GA-pending exemption arms exactly with the installed specjudges their dormancy in both directions. Unlike #4668's five, these do not self-retire on a pin bump — no issue owns declaring them later, by design — and their comment block says so.One bounded fix outside the declared file surface
apps/console/src/__tests__/public-block-binding-reach.test.tsx—SUPERSEDES_BINDINGgainscustomFields.That probe mounts each public block with every declared input filled, then asserts the block asked the data layer for its
objectName. Declaringobject-form.customFieldsturned it red, correctly:ObjectForm.tsx:426computesconst hasInlineFields = schema.customFields && schema.customFields.length > 0, read at:455under "Skip fetching if we have inline fields" — substituting a minimal in-memory object schema for thegetObjectSchema(schema.objectName)call — and again at:479to skip the record fetch. The repo's own type says the same in prose: "When used with inline field definitions (without dataSource), this becomes the primary field source."So a non-empty
customFieldsis the author telling the block not to fetch — precisely the criterion that putdatain that set. The guard is quoted at the entry, as that set's doc requires. Note it is length-sensitive:sampleForreturns['name']for an array input, which is what tripped it.Reported rather than folded in silently: this file is outside the card's declared surface, it is a direct and unavoidable consequence of the declarations, and no in-flight sibling holds it.
Evidence — both pins, at
b58f664(working tree clean)GA readings use PR #4660's npm-pack overlay:
npm pack @objectstack/spec@17.0.0unpacked into this worktree's virtual store with theai/zodpeer links mirrored, all 34@objectstack/specsymlinks repointed, the real suites run unmodified, rc.6 restored after. Version confirmed before each run (17.0.0-rc.6vs17.0.0).registry-inputs-spec-parity.test.ts+ public-block-binding-reach+ public-contractapps/consolefull suiteplugin-formplugin-gridplugin-dashboardsdui-parserapps/consolecustomFieldsfinding above, fixed and re-run greenapp-shell/metadata-adminplugin-designersdui-parsertype-check—plugin-formplugin-gridplugin-dashboardtype-check—apps/consoleeslint --quiet, 5 changed filescheck-control-bytescheck-changeset-presence/-fixed/-no-majorcheck-phantom-dependenciesBoth type-check runs had the dependency closure built first (
pnpm --filter '< pkg >^...' build) — the console's unbuilt run first produced the classic TS2307 / TS2882 false red.Reverse verification — direction predicted first, both pins, from the committed state
Ablation A — delete the
object-grid.titleexemption entry while leaving it pinned inGA_PENDING_UNPUBLISHED_KEYS. Predicted GA 3 / rc.6 1; observed exactly that:The rc.6 asymmetry is the mechanism proving itself: the block assertion stays green there because rc.6 carries no
object-gridkey to demand, which is the dormancy claimed — while the pinned-set guard still fires, so a typo cannot hide.Ablation B — delete a declared input (
object-metric.compareTo). Predicted GA red / rc.6 green:This is the positive control for the sequencing claim above: the declarations are genuinely invisible to rc.6 and genuinely judged on GA, so nothing here can go falsely green at the pin bump.
Both restored with
git checkout < branch > -- < paths >,git statusclean, re-run green on both pins.New assertion added
the four GA blocks resolve their ruled split — declared vs carved outpins the ruling by name rather than leaving it to the derived reverse-direction loop — which goes green just as readily if a declaration is replaced by an exemption, the cheap move under time pressure and the one thing option B forbids. It asserts each carved-out key is spec-declared, un-published and cited, and that every other spec key on the four blocks is declared and carries no exemption, as an exact set difference so a key added by a later GA cannot slip through as neither.Changeset
A real
patchchangeset — this changes published authoring surface on three released packages (@object-ui/plugin-form,@object-ui/plugin-grid,@object-ui/plugin-dashboard). Not an empty-frontmatter one, and noskip-changesetlabel: that label does not exist in this repo.Scope
Five files: three registration sites, the console registry-inputs parity gate, and the console binding-reach probe explained above, plus the changeset. No
content/docs/releases/. In-flight siblings untouched —examples/schema-catalog(#4003),packages/plugin-gantt(#4884),packages/app-shell/src/views/metadata-admin/(#4308).Generated by Claude Code