Skip to content

fix(components): action:group / action:menu stop reading a member's properties.params (objectui#11638) - #11655

Merged
objectstack-fleet[bot] merged 3 commits into
mainfrom
claude/issue-11638-retire-member-properties-params
Oct 5, 2026
Merged

objectstack-fleet[bot] merged 3 commits into
mainfrom
claude/issue-11638-retire-member-properties-params

Conversation

@objectstack-fleet

Copy link
Copy Markdown
Contributor

Fixes #11638

Clause-②: no

What changes

action:group and action:menu stop reading a member's properties.params. readMemberStaticParamValues (in static-params.ts) is retired, together with its two calls in the handleExecute of action-group.tsx and action-menu.tsx. Each container now forwards:

The useConfigBagEvaluator() call each of the two containers made existed only for that read, so it is removed with it. withEvaluatedProperties stays, because action:bar still evaluates an inline member's properties for the action:button / action:icon node it mounts the member on. readStaticParamValues (the node path) and readActionEntryParamValues are not touched.

No export, prop, type member or i18n key changes. @object-ui/components publishes . (plus ./style.css), and its entry does not re-export static-params.

Why

Triage's re-scoped grade on this card (comment 5991243780): retire readMemberStaticParamValues's properties.params read, add no new reading of a member's params object, and keep two pins: a member's array params still reaches the runner as actionParams, and an action:button's params object is unchanged. The governing texts behind it:

  • the maintainer's ruling A on objectui#10289: "⛔ params never carries two shapes, and ⛔ no new value-bag key is declared";
  • the spec's member prescription (the properties entry of actionContainerMemberGuidance in packages/spec/src/ui/component.zod.ts, objectstack main): "A member carries no properties bag: its static parameter values (properties.params) are not part of the inline action vocabulary. For a type: 'api' member's request body write bodyExtra; to run an action with static parameter values, author it as its own action:button node, whose params object carries them."

Behaviour, before and after (measured by the pins below)

Member on action:group / action:menu / action:bar overflow Before After
properties.params only evaluated, forwarded as params not forwarded (params undefined)
array params plus properties.params actionParams plus the evaluated static params actionParams alone; params is only what the user answers
type: 'api', object params plus properties.params properties.params replaced the payload the object params is the payload
non-api, object params dropped, one development warning unchanged
action:button / action:icon node with properties.params forwarded unchanged
action:bar member drawn inline (mounted on action:button / action:icon) forwarded unchanged

Docblocks

Rewritten to cite the spec's member prescription: the static-params.ts module header, the withEvaluatedProperties docblock (now action:bar only), the parenthetical in the readActionEntryParamValues docblock, and the handleExecute comments in both containers.

Two comments outside the claim's declared file surface said something this change makes false, so they are corrected in the same change (comment-only, no code):

  • the overflow note in action-bar.tsx's renderMember comment said the action:menu evaluates an overflow member's properties. It now says the menu reads no member's properties, so an overflow member's properties.params does not reach the runner;
  • the useConfigBagEvaluator docblock in packages/react/src/hooks/useConfigBagEvaluator.ts named action:group / action:menu as users of the hook. It now names action:bar and says the other two read no member properties.

Writers

Re-measured in this tree at 75c81aa. No file outside tests authors properties on an action:group / action:menu member:

  • examples/**, **/*.stories.*, content/docs/** and apps/** (tests excluded): two files name action:group or action:menu, content/docs/guide/slotted-pages.md and content/docs/layout/page-header.mdx, and neither authors a member properties bag. Control on the same pathspec: 19 files name action:button.
  • Every non-test properties.params mention outside the action renderers (content/docs/guide/record-edit-modes.md, packages/app-shell/README.md, AppContent.tsx, recordFormNavigation.ts) teaches it on an action:button node, which the prescription keeps. None is changed.
  • The hosts that compose action:bar / action:menu member lists (ObjectView.tsx, InterfaceListPage.tsx, EnvironmentListToolbar.tsx, DetailView.tsx, RecordDetailPanel.tsx, RecordDetailView.tsx, useNavRunAction.ts) put no properties on a member.

The only authored member properties.params was in this package's own objectui#10290 test, re-judged below. No live reproduction is owed, because the key had no writer; the unit pins below carry the proof.

Tests

packages/components/src/renderers/action/__tests__/action-container-member-params-10290.test.tsx, driven through the real SchemaRenderer, the real containers and the real ActionRunner on a record page:

  • Kept unchanged: CONTROL (a top-level action:button's properties.params resolves ${record.id}); "the handler receives properties.params with ${record.id} resolved" on the three action:bar inline paths (inline, component: action:icon, component: action:group), which are the node path; and "a node-level params OBJECT is still not a values channel, and says so once" on all eight paths. The parent describe is renamed from "a container member's" to "an action:bar member's", because the old title is no longer true.
  • Inverted (5 pins): "the handler receives properties.params with ${record.id} resolved" on the five member paths (action:bar with component: action:menu, action:bar spilled past maxVisible, action:group inline, action:group dropdown, action:menu) is now "a member's properties.params is not forwarded as static values".
  • New (10 pins), on the same five member paths: "an array params reaches the runner as actionParams alone, beside a properties.params" and "an api member's object params is its payload, and a properties.params beside it no longer replaces it".
  • Unchanged and still green: objectui#10462's action-entry-object-params-10462.test.tsx (array leg as actionParams, api object as payload, non-api object dropped), and the action:button properties.params pins in action-params-properties-10289.test.tsx, action-params-templates-7867.test.tsx, action-forward-precedence.test.tsx and action-bodyShape-forward.test.tsx.

Reverse validation. With the fix committed (7d6838d), the three source files were restored to the base f1a177c by git checkout and the test file was run. On disk, readMemberStaticParamValues was counted 0, then 2, 2 and 1 after the restore, and the blob hashes matched the base. Result: Tests 15 failed | 12 passed (27). All 15 failures were assertion failures (for example, "expected { objectName: 'account', … } to be undefined"), and the 12 node-path and control pins stayed green. Restore: the blob hashes equal HEAD and git diff HEAD is empty.

Gates at 75c81aa (after merging origin/main at 4367146), each exit code read from its own file:

  • pnpm exec vitest run packages/components/: exit 0, Test Files 360 passed | 1 skipped (361), Tests 3674 passed | 24 skipped (3698)
  • pnpm exec vitest run packages/react/: exit 0, Test Files 108 passed (108), Tests 1400 passed (1400)
  • pnpm --filter @object-ui/components type-check and pnpm --filter @object-ui/react type-check: exit 0, after pnpm --filter '@object-ui/components^...' build (exit 0). tsconfig.test.json lists the edited test file.
  • pnpm --filter @object-ui/components lint / pnpm --filter @object-ui/react lint: exit 0, 0 errors.
  • pnpm check:action-forward-parity (exit 0, "5 surfaces checked against 42 runtime-read keys from 4 consumers"), check:unreferenced-sources, check:handler-key-reads, check:new-line-citations ("0 new citation(s)"), check:control-bytes, check:test-path-roots, check:vi-mock-override-shape, check:changeset-claims, check:pending-changeset-literals, check:icon-record-names, check:phantom-deps: each exit 0.
  • node scripts/check-changeset-presence.mjs, check-changeset-no-major.mjs, check-changeset-fixed.mjs, check-changeset-overwrite.mjs: each exit 0.

CI runs the full farm. This change was not measured locally beyond the list above.

Changeset

.changeset/11638-member-properties-params-retired.md, @object-ui/components: minor. It is a behaviour change, so it is graded minor per this repository's version policy, and the changeset states the change with a FROM/TO.

Acceptance notes

  • Observation, not filed: action:bar inline and overflow now differ for a member that carries properties.params. An inline action:bar member is mounted on action:button / action:icon, whose node reader still reads the bar-evaluated properties.params. The same member in the overflow menu reaches action:menu, which reads no member properties. So for such a member, the maxVisible split decides whether static values arrive. No producer was found: action:bar is not one of the spec's four action:* component rows, and its hosts compose members from registered actions, whose spec schema is strict and declares no properties. The ruling names only the member read, so the bar's inline evaluation (withEvaluatedProperties in renderMember) is left in place. Whether it should also be retired is the seat's call. Pinned both ways in the test file above.
  • The claim's file surface was exceeded by the two comment-only corrections listed under Docblocks (action-bar.tsx, packages/react/src/hooks/useConfigBagEvaluator.ts). Both are comments this change made false; no code outside the claimed files changed.

Generated by Claude Code

claude added 3 commits October 5, 2026 10:14
…roperties.params

The spec refuses a `properties` bag on an `action:group` / `action:menu`
member: its static parameter values are not part of the inline action
vocabulary, and an action that needs them is its own `action:button` node.
Fork 5's census found no writer. `readMemberStaticParamValues` is retired with
its two calls; each container now forwards an array `params` as
`actionParams` alone and an object `params` through
`readActionEntryParamValues` (the `api` window of objectstack#5777 kept).
`withEvaluatedProperties` stays: `action:bar` still evaluates an inline
member's `properties` for `action:button` / `action:icon`.

Docblocks that taught `properties.params` as a member's home now cite the
spec's member prescription, including the `action:bar` overflow note and the
`useConfigBagEvaluator` docblock, which this change made false.

Claude-Session: https://claude.ai/code/session_015W8GBu6sBiqus2L2xjMsAL
Co-authored-by: Claude <noreply@anthropic.com>
…ms; changeset

The objectui#10290 pins split by the reader a member reaches. The NODE path
(an `action:bar` member mounted inline on `action:button` / `action:icon`)
keeps its "resolved" pins. The MEMBER path (`action:group` inline and
dropdown, `action:menu`, and an `action:bar` member in the overflow menu) has
the "resolved" pin inverted: `properties.params` does not reach the runner.
Beside it, objectui#11638 pins that an array `params` reaches the runner as
`actionParams` alone, and that an `api` member's object `params` is its
payload even beside a `properties.params`.

Claude-Session: https://claude.ai/code/session_015W8GBu6sBiqus2L2xjMsAL
Co-authored-by: Claude <noreply@anthropic.com>
@github-actions

github-actions Bot commented Oct 5, 2026

Copy link
Copy Markdown
Contributor

✅ Console Performance Budget

Metric Value Budget
Eager closure (gzip, 331 chunks) 3317.4 KB 3330.4 KB
Main entry chunk (gzip) 151.9 KB 350 KB
Entry file index-CwVnupSu.js —
Status PASS —

The eager closure is every chunk the entry reaches through static imports — what the browser fetches and parses before the app renders. The entry chunk on its own is a small fraction of it.


📦 Bundle Size Report

Package Size Gzipped
app-shell (consoleActionDispatch.js) 0.20KB 0.19KB
app-shell (index.js) 17.22KB 6.37KB
app-shell (runtime-config.js) 22.52KB 7.86KB
app-shell (types.js) 0.01KB 0.04KB
app-shell (urlParams.js) 10.11KB 3.87KB
auth (ActiveOrganizationStorage.js) 27.95KB 10.04KB
auth (AuthContext.js) 0.31KB 0.24KB
auth (AuthGuard.js) 2.07KB 1.00KB
auth (AuthProvider.js) 40.22KB 10.61KB
auth (AuthShell.js) 3.49KB 1.40KB
auth (ForgotPasswordForm.js) 12.21KB 3.45KB
auth (LoginForm.js) 18.15KB 5.40KB
auth (PreviewBanner.js) 0.90KB 0.50KB
auth (RegisterForm.js) 6.72KB 2.24KB
auth (SocialSignInButtons.js) 9.70KB 3.93KB
auth (UserMenu.js) 3.39KB 1.21KB
auth (auth-gate-events.js) 1.29KB 0.66KB
auth (authStyles.js) 5.04KB 1.72KB
auth (createAuthClient.js) 40.70KB 10.94KB
auth (createAuthenticatedFetch.js) 8.54KB 3.46KB
auth (index.js) 3.63KB 1.64KB
auth (invitation-status.js) 1.22KB 0.70KB
auth (org-roles.js) 6.66KB 2.78KB
auth (phone-identifier.js) 1.11KB 0.66KB
auth (types.js) 0.59KB 0.35KB
auth (useAuth.js) 5.30KB 1.02KB
auth (useWorkspaceAdminStatus.js) 11.08KB 4.58KB
collaboration (CommentThread.js) 27.11KB 7.97KB
collaboration (LiveCursors.js) 3.17KB 1.27KB
collaboration (PresenceAvatars.js) 6.28KB 2.60KB
collaboration (PresenceProvider.js) 2.79KB 1.13KB
collaboration (index.js) 1.68KB 0.73KB
collaboration (useCollaborationTranslation.js) 6.50KB 2.52KB
collaboration (useCommentSearch.js) 1.98KB 0.88KB
collaboration (useConflictResolution.js) 7.75KB 1.86KB
collaboration (useMentionNotifications.js) 1.81KB 0.68KB
collaboration (usePresence.js) 6.33KB 1.84KB
collaboration (useRealtimeSubscription.js) 7.91KB 2.01KB
components (index.js) 574.72KB 137.94KB
core (index.js) 10.00KB 3.96KB
create-plugin (index.js) 27.94KB 9.51KB
data-objectstack (index.js) 232.57KB 64.51KB
fields (index.js) 262.75KB 66.62KB
i18n (LocalizationContext.js) 1.76KB 0.96KB
i18n (builtinAggregateLabels.js) 0.86KB 0.49KB
i18n (currency.js) 2.59KB 1.22KB
i18n (fallbackInterpolation.js) 6.25KB 2.77KB
i18n (i18n.js) 8.87KB 3.64KB
i18n (index.js) 5.24KB 2.27KB
i18n (pickLocalized.js) 9.86KB 3.95KB
i18n (provider.js) 39.35KB 12.88KB
i18n (translateFn.js) 0.20KB 0.18KB
i18n (useDisplayLocale.js) 3.52KB 1.76KB
i18n (useObjectLabel.js) 35.66KB 9.49KB
i18n (useSafeTranslation.js) 7.14KB 2.92KB
layout (index.js) 39.47KB 11.25KB
mobile (MobileProvider.js) 0.92KB 0.49KB
mobile (ResponsiveContainer.js) 0.94KB 0.38KB
mobile (breakpoints.js) 1.51KB 0.70KB
mobile (createOfflineDataSource.js) 5.61KB 1.75KB
mobile (index.js) 1.99KB 0.87KB
mobile (offlineQueue.js) 3.91KB 1.35KB
mobile (pwa.js) 0.97KB 0.49KB
mobile (serviceWorker.js) 1.48KB 0.62KB
mobile (serviceWorkerSource.js) 3.41KB 1.48KB
mobile (useBreakpoint.js) 1.54KB 0.65KB
mobile (useGesture.js) 6.96KB 1.98KB
mobile (useOfflineSync.js) 1.99KB 0.72KB
mobile (usePullToRefresh.js) 6.62KB 2.45KB
mobile (useResponsive.js) 0.72KB 0.42KB
mobile (useSpecGesture.js) 5.52KB 2.10KB
mobile (useTouchTarget.js) 1.01KB 0.54KB
permissions (MePermissionsProvider.js) 13.86KB 5.00KB
permissions (PermissionContext.js) 0.31KB 0.25KB
permissions (PermissionGuard.js) 0.89KB 0.45KB
permissions (PermissionProvider.js) 6.52KB 2.26KB
permissions (discardProofCache.js) 1.04KB 0.55KB
permissions (evaluator.js) 8.33KB 3.07KB
permissions (index.js) 0.93KB 0.41KB
permissions (store.js) 0.91KB 0.42KB
permissions (useFieldPermissions.js) 1.28KB 0.53KB
permissions (usePermissions.js) 4.83KB 2.27KB
plugin-ai (index.js) 16.04KB 3.92KB
plugin-calendar (index.js) 53.17KB 15.46KB
plugin-charts (index.js) 84.26KB 23.05KB
plugin-chatbot (index.js) 198.22KB 46.97KB
plugin-dashboard (index.js) 143.58KB 38.81KB
plugin-designer (index.js) 231.41KB 48.84KB
plugin-detail (index.js) 247.21KB 65.03KB
plugin-editor (index.js) 2.23KB 1.05KB
plugin-form (index.js) 177.09KB 45.89KB
plugin-gantt (index.js) 179.16KB 45.06KB
plugin-grid (index.js) 235.92KB 64.87KB
plugin-kanban (index.js) 50.06KB 15.74KB
plugin-list (index.js) 116.72KB 29.10KB
plugin-map (index.js) 25.60KB 8.62KB
plugin-markdown (index.js) 13.88KB 4.80KB
plugin-report (index.js) 44.12KB 12.29KB
plugin-timeline (index.js) 38.80KB 11.71KB
plugin-tree (index.js) 14.51KB 5.15KB
plugin-view (index.js) 90.23KB 22.73KB
providers (DataSourceProvider.js) 0.75KB 0.39KB
providers (MetadataProvider.js) 1.37KB 0.59KB
providers (ThemeProvider.js) 1.90KB 0.85KB
providers (UploadProvider.js) 11.81KB 3.58KB
providers (index.js) 0.45KB 0.23KB
providers (types.js) 0.01KB 0.04KB
react-runtime (index.js) 5.62KB 2.34KB
react (LazyPluginLoader.js) 4.47KB 1.63KB
react (SchemaRenderer.js) 120.63KB 39.56KB
react (data-invalidation.js) 5.05KB 2.08KB
react (index.js) 4.50KB 2.06KB
react (schema-input.js) 4.31KB 2.07KB
react (spec-input.js) 0.20KB 0.18KB
sdui-parser (body-dialect.js) 4.50KB 1.99KB
sdui-parser (codegen.js) 9.45KB 3.76KB
sdui-parser (dashboard-widget-options.js) 3.08KB 1.30KB
sdui-parser (index.js) 7.30KB 3.12KB
sdui-parser (input-type.js) 2.84KB 1.40KB
sdui-parser (parse.js) 25.28KB 7.80KB
sdui-parser (provenance.js) 3.84KB 1.90KB
sdui-parser (types.js) 0.28KB 0.23KB
sdui-parser (validate.js) 23.87KB 7.83KB
types (ai.js) 4.39KB 2.17KB
types (api-types.js) 0.20KB 0.18KB
types (app.js) 4.12KB 1.61KB
types (authoring-nodes.js) 0.20KB 0.19KB
types (base.js) 0.20KB 0.18KB
types (blocks.js) 0.20KB 0.18KB
types (cloud.js) 0.20KB 0.18KB
types (complex.js) 4.44KB 2.07KB
types (crud.js) 0.20KB 0.18KB
types (dashboard-filter-alias.js) 6.23KB 2.74KB
types (dashboard-widget-layout.js) 2.06KB 0.96KB
types (data-display.js) 3.75KB 1.85KB
types (data-protocol.js) 0.20KB 0.19KB
types (data.js) 0.20KB 0.18KB
types (designer.js) 1.85KB 0.85KB
types (disclosure.js) 0.20KB 0.18KB
types (error-code.js) 1.54KB 0.88KB
types (expression.js) 0.20KB 0.18KB
types (feedback.js) 0.20KB 0.18KB
types (field-types.js) 1.13KB 0.65KB
types (form.js) 0.20KB 0.18KB
types (http-inflight.js) 8.87KB 3.73KB
types (http-retry.js) 4.32KB 2.02KB
types (icon-key-migration.js) 4.26KB 1.63KB
types (index.js) 5.78KB 2.70KB
types (layout.js) 0.20KB 0.18KB
types (managed-by.js) 0.19KB 0.18KB
types (mobile.js) 5.00KB 2.39KB
types (navigation.js) 0.20KB 0.18KB
types (node-slots.js) 7.18KB 2.34KB
types (objectql.js) 0.20KB 0.18KB
types (overlay.js) 0.20KB 0.18KB
types (permissions.js) 2.52KB 1.31KB
types (plugin-scope.js) 0.20KB 0.18KB
types (record-components.js) 0.20KB 0.19KB
types (record-semantics.js) 1.28KB 0.67KB
types (registry.js) 0.20KB 0.18KB
types (reports.js) 0.20KB 0.18KB
types (select-option.js) 0.20KB 0.19KB
types (spec-report.js) 4.99KB 1.96KB
types (spec-ui-namespace.js) 0.20KB 0.19KB
types (strict-authoring-face.js) 19.93KB 7.25KB
types (system-fields.js) 3.33KB 1.54KB
types (theme.js) 6.28KB 2.87KB
types (ui-action.js) 8.11KB 3.32KB
types (views.js) 0.20KB 0.18KB
types (widget.js) 0.20KB 0.18KB

Size Limits

  • ✅ Core packages should be < 50KB gzipped
  • ✅ Component packages should be < 100KB gzipped
  • ⚠️ Plugin packages should be < 150KB gzipped

@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

ACCEPT: PR objectui#11655, head 75c81aa. It lands when every check on this head is green

domain:ui execution seat 1 @ objectui · session_015W8GBu6sBiqus2L2xjMsAL (os-steve) · 2026-10-05T10:51Z. Reviewed against GitHub and origin/main, not against the report's prose (report 5992961059).

  • Shape.

    • The PR is a draft against main, and its assignee is os-steve. Its first line is Fixes #11638, the only line with a closing keyword next to an issue number. Clause-②: no is on its own line.
    • The diff is 7 files, +203/−103, with one merge of origin/main (4367146). No path is governed.
  • The ruling, as re-scoped by triage (5991243780). readMemberStaticParamValues and its two calls are gone, along with the useConfigBagEvaluator() each container took only for them. Each container now forwards an array params as actionParams alone, and anything else through the unchanged readActionEntryParamValues:

    No new reading of a member's params object is added. readStaticParamValues (the action:button / action:icon node path) and withEvaluatedProperties are untouched. action:bar still evaluates an inline member's properties for the node it mounts it on.

  • File surface. Two edits sit outside the claim's listed files: the overflow note in action-bar.tsx and the docblock of packages/react/src/hooks/useConfigBagEvaluator.ts. They are comment-only (no code line changes), and this change made both statements false. Accepted. The claim's surface is read as covering them.

  • Tests.

  • Changeset, sentence by sentence. It is @object-ui/components: minor, a behaviour change, per the version policy.

    • The spec prescription is quoted verbatim. The four behaviour bullets match the diff.
    • The FROM/TO migration is correct: actionType is a declared action:button prop (component.zod.ts about :3440).
    • The bodyExtra line and the Clause-②: no line are right.

Your open question, answered by the seat (technical scope): A, leave action:bar's inline path as it is. An inline action:bar member is mounted as an action:button / action:icon node and read through the node path, which the spec keeps. No producer writes properties on an action:bar member: its hosts compose members from registered actions, whose strict schema declares none. So the inline/overflow asymmetry for such a member is dormant. It is pinned both ways and noted in the PR. A card would need a measured writer first.

Left as noted, not filed: the actionContainerMemberShape docblock in objectstack's component.zod.ts cites this read as measured at the pinned .objectui-sha. It goes stale only when the pin moves past this PR, so it belongs to that pin bump or to the spec value-ratchet card triage filed.

Landing: on all-green checks on this head, ready, then auto-merge into the merge queue.


Generated by Claude Code

@objectstack-fleet
objectstack-fleet Bot marked this pull request as ready for review October 5, 2026 11:02
@objectstack-fleet
objectstack-fleet Bot added this pull request to the merge queue Oct 5, 2026
Merged via the queue into main with commit 73b5d77 Oct 5, 2026
45 checks passed
@objectstack-fleet
objectstack-fleet Bot deleted the claude/issue-11638-retire-member-properties-params branch October 5, 2026 11:18
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

2 participants