From df91678a2265d26d0e01010f79c6ddcdf4489640 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 10 Aug 2026 01:45:59 +0000 Subject: [PATCH] chore: release packages --- ...n-bar-member-declared-visible-gate-3823.md | 47 - .../action-declared-disabled-gate-3842.md | 52 - ...tion-member-declared-disabled-gate-3849.md | 50 - ...ction-member-declared-visible-gate-3812.md | 37 - ...ion-param-datetime-zoned-instant-os5061.md | 55 - ...ion-runner-declared-condition-gate-3872.md | 59 - ...tion-runner-declared-disabled-gate-3848.md | 54 - .../actionparamdialog-boolean-host-id-3962.md | 30 - .../address-field-postal-code-os5143.md | 31 - .../appcontent-route-test-headers-3749.md | 30 - .../auth-family-locale-keys-3546-slice3.md | 50 - .../block-config-placeholder-i18n-3979.md | 46 - .../boolean-field-host-owns-control-id.md | 9 - .changeset/builtin-select-host-id-3976.md | 35 - .../bulk-action-param-options-open-3309.md | 25 - .../bulkactiondialog-required-aria-3967.md | 31 - ...ability-multiselect-widget-retired-3308.md | 23 - ...t-container-min-size-style-merge-os7026.md | 49 - .changeset/cli-app-generator-manifest-3827.md | 69 -- .../cli-generated-app-tailwind-v4-3852.md | 17 - .changeset/compareto-kind-convergence.md | 14 - ...ts-export-declared-visibility-gate-3835.md | 21 - .../components-readme-setup-tailwind-3780.md | 54 - .../composite-group-label-association-3961.md | 32 - .changeset/console-locale-keys-3546-slice4.md | 67 -- ...ontext-selector-auto-select-race-os6979.md | 35 - .../create-plugin-build-deps-anchored-3742.md | 15 - .../create-plugin-runnable-test-stack.md | 19 - ...lugin-scaffold-dead-artifacts-3755-3759.md | 46 - .changeset/data-table-row-menu-empty-guard.md | 18 - .../dataset-drill-ranges-passthrough-3813.md | 43 - .../dataset-result-fields-spec-type-3752.md | 38 - .../dataset-selection-spec-type-3613.md | 38 - ...-widget-chartconfig-presentation-os7016.md | 51 - .../dataset-widget-colorvariant-3359.md | 45 - .changeset/de-approvals-inbox-quotes-3919.md | 41 - .changeset/de-quote-pairing-3876.md | 57 - .../declared-actions-bar-visible-gate-3835.md | 58 - .changeset/default-list-view-identity-3770.md | 12 - .changeset/div-deprecation-warn-once.md | 18 - .changeset/draftbar-es-register-3844.md | 65 -- .../element-datasource-block-wiring-os6953.md | 58 - ...ment-datasource-remaining-blocks-os7121.md | 54 - .changeset/element-datasource-view-os5576.md | 49 - ...empty-predicate-declared-gate-3850-3862.md | 74 -- ...onment-create-cta-loading-skeleton-3482.md | 24 - ...es-readonly-failopen-server-parity-3828.md | 34 - .changeset/fields-catalog-form-hosted-3910.md | 16 - .../fields-readonly-group-label-idref-3990.md | 57 - .changeset/forward-bodyshape-os6938.md | 30 - .../grid-import-saved-mapping-i18n-3920.md | 61 - .changeset/grid-import-transform-i18n-3938.md | 47 - ...header-action-predicates-speak-cel-3521.md | 32 - ...hlights-readonly-authoring-surface-3407.md | 35 - ...itl-decision-outcomes-spec-derived-3783.md | 43 - .changeset/home-administration-group-3609.md | 9 - .../host-redirect-canonical-metadata-3639.md | 12 - .changeset/inputs-reverse-parity-3808.md | 53 - .../inspector-combo-field-label-3997.md | 19 - .../inspector-shared-field-labels-3994.md | 41 - .changeset/layout-inputs-declaration-3972.md | 38 - .../layout-sideeffects-registration-3899.md | 65 -- .changeset/lucky-pears-translate.md | 18 - .changeset/lucky-pugs-shave.md | 28 - ...etplace-preview-locale-keys-3546-slice5.md | 46 - ...dicate-unresolved-path-fail-open-os6936.md | 61 - .changeset/multiselect-group-label-3975.md | 31 - .../nav-canonical-metadata-routes-3660.md | 12 - .../nav-sys-objects-canonical-route-3739.md | 13 - .changeset/navigation-items-required-3987.md | 30 - .../no-app-component-metadata-routes-3610.md | 9 - .../no-apps-create-first-app-cta-3573.md | 26 - .../no-apps-go-to-settings-target-3590.md | 7 - .changeset/objectstack-family-rc5-refresh.md | 105 -- .changeset/objectview-value-language-3582.md | 43 - .changeset/olive-donkeys-repeat.md | 27 - .../organization-namespace-slice-two.md | 33 - ...os5994-context-selector-persist-enforce.md | 5 - ...tbound-agent-conversation-language-3896.md | 46 - .../page-block-inspector-chrome-i18n.md | 15 - ...block-inspector-curated-label-i18n-3913.md | 41 - .changeset/page-header-is-container-3900.md | 36 - .../percent-cell-value-over-bar-os5066.md | 33 - .changeset/pivot-compare-stacking-3614.md | 16 - .../plan-building-label-ui-locale-3837.md | 40 - ...-map-drop-module-scope-console-log-7139.md | 27 - .../plugin-report-react-19-peer-3690.md | 11 - ...edicate-input-template-double-wrap-3871.md | 43 - ...predicate-scope-converge-3955-3957-3960.md | 73 -- .changeset/pseudo-route-segment-flags-3638.md | 9 - .changeset/quiet-doors-forward-bodyextra.md | 23 - .changeset/quiet-moons-inherit.md | 26 - .changeset/quota-error-envelope-3491.md | 24 - .changeset/raw-key-call-sites-slice-one.md | 17 - .../react-runtime-peer-upper-bound-3741.md | 13 - .../reclaim-natural-gesture-names-3363.md | 58 - ...ecord-details-sections-description-3807.md | 32 - ...ecord-details-sections-name-anchor-3819.md | 56 - .../record-header-manual-refresh-3460.md | 17 - .../registry-inputs-spec-parity-gate-3797.md | 25 - .../related-list-add-picker-filter-3831.md | 17 - .../related-list-add-picker-guard-3838.md | 7 - .../related-list-filter-and-add-gate.md | 25 - .changeset/remaining-setup-links-3611.md | 15 - .changeset/residue-locale-keys-3546-slice7.md | 63 - .../row-action-declared-visible-gate-3758.md | 33 - .../row-action-inline-slot-survivors-3762.md | 39 - .changeset/rowactionmenu-empty-guard.md | 25 - .../runner-preserve-query-on-navigate.md | 5 - .../runner-vite-alias-transitive-closure.md | 29 - .changeset/schemaform-visiblewhen-os6331.md | 48 - .../select-multiple-widget-mapping-3986.md | 16 - .changeset/sour-clouds-yawn.md | 22 - .../system-hub-count-error-state-3679.md | 23 - .changeset/system-hub-org-count-3670.md | 11 - .changeset/system-hub-permissions-leg-3655.md | 17 - .changeset/system-hub-routes-3655.md | 14 - ...eline-line-items-filter-sort-limit-7137.md | 57 - .changeset/user-filters-button-type-os6952.md | 32 - ...filters-allowaddtab-session-tabs-os5236.md | 13 - .changeset/view-edit-wire-gate-5316.md | 30 - .changeset/view-overrides-readback.md | 13 - .../view-readonly-tooltip-semantics-3625.md | 41 - .../view-translation-keys-bare-only-3502.md | 15 - apps/console/CHANGELOG.md | 87 +- apps/console/package.json | 2 +- packages/app-shell/CHANGELOG.md | 1038 ++++++++++++++++- packages/app-shell/package.json | 2 +- packages/auth/CHANGELOG.md | 13 + packages/auth/package.json | 2 +- packages/cli/CHANGELOG.md | 119 ++ packages/cli/package.json | 2 +- packages/collaboration/CHANGELOG.md | 28 + packages/collaboration/package.json | 2 +- packages/components/CHANGELOG.md | 667 ++++++++++- packages/components/package.json | 2 +- packages/core/CHANGELOG.md | 605 ++++++++++ packages/core/package.json | 2 +- packages/create-plugin/CHANGELOG.md | 75 ++ packages/create-plugin/package.json | 2 +- packages/data-objectstack/CHANGELOG.md | 255 ++++ packages/data-objectstack/package.json | 2 +- packages/fields/CHANGELOG.md | 303 +++++ packages/fields/package.json | 2 +- packages/i18n/CHANGELOG.md | 641 +++++++++- packages/i18n/package.json | 2 +- packages/layout/CHANGELOG.md | 205 ++++ packages/layout/package.json | 2 +- packages/mobile/CHANGELOG.md | 173 +++ packages/mobile/package.json | 2 +- packages/permissions/CHANGELOG.md | 12 + packages/permissions/package.json | 2 +- packages/plugin-ai/CHANGELOG.md | 40 + packages/plugin-ai/package.json | 2 +- packages/plugin-calendar/CHANGELOG.md | 122 ++ packages/plugin-calendar/package.json | 2 +- packages/plugin-charts/CHANGELOG.md | 163 +++ packages/plugin-charts/package.json | 2 +- packages/plugin-chatbot/CHANGELOG.md | 122 ++ packages/plugin-chatbot/package.json | 2 +- packages/plugin-dashboard/CHANGELOG.md | 276 +++++ packages/plugin-dashboard/package.json | 2 +- packages/plugin-designer/CHANGELOG.md | 85 ++ packages/plugin-designer/package.json | 2 +- packages/plugin-detail/CHANGELOG.md | 337 ++++++ packages/plugin-detail/package.json | 2 +- packages/plugin-editor/CHANGELOG.md | 43 + packages/plugin-editor/package.json | 2 +- packages/plugin-form/CHANGELOG.md | 258 ++++ packages/plugin-form/package.json | 2 +- packages/plugin-gantt/CHANGELOG.md | 135 +++ packages/plugin-gantt/package.json | 2 +- packages/plugin-grid/CHANGELOG.md | 250 ++++ packages/plugin-grid/package.json | 2 +- packages/plugin-kanban/CHANGELOG.md | 135 +++ packages/plugin-kanban/package.json | 2 +- packages/plugin-list/CHANGELOG.md | 92 ++ packages/plugin-list/package.json | 2 +- packages/plugin-map/CHANGELOG.md | 113 ++ packages/plugin-map/package.json | 2 +- packages/plugin-markdown/CHANGELOG.md | 43 + packages/plugin-markdown/package.json | 2 +- packages/plugin-report/CHANGELOG.md | 85 ++ packages/plugin-report/package.json | 2 +- packages/plugin-timeline/CHANGELOG.md | 160 +++ packages/plugin-timeline/package.json | 2 +- packages/plugin-tree/CHANGELOG.md | 55 + packages/plugin-tree/package.json | 2 +- packages/plugin-view/CHANGELOG.md | 63 + packages/plugin-view/package.json | 2 +- packages/providers/CHANGELOG.md | 17 + packages/providers/package.json | 2 +- packages/react-runtime/CHANGELOG.md | 14 + packages/react-runtime/package.json | 2 +- packages/react/CHANGELOG.md | 388 ++++++ packages/react/package.json | 2 +- packages/runner/CHANGELOG.md | 72 ++ packages/runner/package.json | 2 +- packages/sdui-parser/CHANGELOG.md | 2 + packages/sdui-parser/package.json | 2 +- packages/types/CHANGELOG.md | 248 ++++ packages/types/package.json | 2 +- packages/vscode-extension/CHANGELOG.md | 23 + packages/vscode-extension/package.json | 2 +- 204 files changed, 7597 insertions(+), 4267 deletions(-) delete mode 100644 .changeset/action-bar-member-declared-visible-gate-3823.md delete mode 100644 .changeset/action-declared-disabled-gate-3842.md delete mode 100644 .changeset/action-member-declared-disabled-gate-3849.md delete mode 100644 .changeset/action-member-declared-visible-gate-3812.md delete mode 100644 .changeset/action-param-datetime-zoned-instant-os5061.md delete mode 100644 .changeset/action-runner-declared-condition-gate-3872.md delete mode 100644 .changeset/action-runner-declared-disabled-gate-3848.md delete mode 100644 .changeset/actionparamdialog-boolean-host-id-3962.md delete mode 100644 .changeset/address-field-postal-code-os5143.md delete mode 100644 .changeset/appcontent-route-test-headers-3749.md delete mode 100644 .changeset/auth-family-locale-keys-3546-slice3.md delete mode 100644 .changeset/block-config-placeholder-i18n-3979.md delete mode 100644 .changeset/boolean-field-host-owns-control-id.md delete mode 100644 .changeset/builtin-select-host-id-3976.md delete mode 100644 .changeset/bulk-action-param-options-open-3309.md delete mode 100644 .changeset/bulkactiondialog-required-aria-3967.md delete mode 100644 .changeset/capability-multiselect-widget-retired-3308.md delete mode 100644 .changeset/chart-container-min-size-style-merge-os7026.md delete mode 100644 .changeset/cli-app-generator-manifest-3827.md delete mode 100644 .changeset/cli-generated-app-tailwind-v4-3852.md delete mode 100644 .changeset/compareto-kind-convergence.md delete mode 100644 .changeset/components-export-declared-visibility-gate-3835.md delete mode 100644 .changeset/components-readme-setup-tailwind-3780.md delete mode 100644 .changeset/composite-group-label-association-3961.md delete mode 100644 .changeset/console-locale-keys-3546-slice4.md delete mode 100644 .changeset/context-selector-auto-select-race-os6979.md delete mode 100644 .changeset/create-plugin-build-deps-anchored-3742.md delete mode 100644 .changeset/create-plugin-runnable-test-stack.md delete mode 100644 .changeset/create-plugin-scaffold-dead-artifacts-3755-3759.md delete mode 100644 .changeset/data-table-row-menu-empty-guard.md delete mode 100644 .changeset/dataset-drill-ranges-passthrough-3813.md delete mode 100644 .changeset/dataset-result-fields-spec-type-3752.md delete mode 100644 .changeset/dataset-selection-spec-type-3613.md delete mode 100644 .changeset/dataset-widget-chartconfig-presentation-os7016.md delete mode 100644 .changeset/dataset-widget-colorvariant-3359.md delete mode 100644 .changeset/de-approvals-inbox-quotes-3919.md delete mode 100644 .changeset/de-quote-pairing-3876.md delete mode 100644 .changeset/declared-actions-bar-visible-gate-3835.md delete mode 100644 .changeset/default-list-view-identity-3770.md delete mode 100644 .changeset/div-deprecation-warn-once.md delete mode 100644 .changeset/draftbar-es-register-3844.md delete mode 100644 .changeset/element-datasource-block-wiring-os6953.md delete mode 100644 .changeset/element-datasource-remaining-blocks-os7121.md delete mode 100644 .changeset/element-datasource-view-os5576.md delete mode 100644 .changeset/empty-predicate-declared-gate-3850-3862.md delete mode 100644 .changeset/environment-create-cta-loading-skeleton-3482.md delete mode 100644 .changeset/fieldrules-readonly-failopen-server-parity-3828.md delete mode 100644 .changeset/fields-catalog-form-hosted-3910.md delete mode 100644 .changeset/fields-readonly-group-label-idref-3990.md delete mode 100644 .changeset/forward-bodyshape-os6938.md delete mode 100644 .changeset/grid-import-saved-mapping-i18n-3920.md delete mode 100644 .changeset/grid-import-transform-i18n-3938.md delete mode 100644 .changeset/header-action-predicates-speak-cel-3521.md delete mode 100644 .changeset/highlights-readonly-authoring-surface-3407.md delete mode 100644 .changeset/hitl-decision-outcomes-spec-derived-3783.md delete mode 100644 .changeset/home-administration-group-3609.md delete mode 100644 .changeset/host-redirect-canonical-metadata-3639.md delete mode 100644 .changeset/inputs-reverse-parity-3808.md delete mode 100644 .changeset/inspector-combo-field-label-3997.md delete mode 100644 .changeset/inspector-shared-field-labels-3994.md delete mode 100644 .changeset/layout-inputs-declaration-3972.md delete mode 100644 .changeset/layout-sideeffects-registration-3899.md delete mode 100644 .changeset/lucky-pears-translate.md delete mode 100644 .changeset/lucky-pugs-shave.md delete mode 100644 .changeset/marketplace-preview-locale-keys-3546-slice5.md delete mode 100644 .changeset/metadata-admin-predicate-unresolved-path-fail-open-os6936.md delete mode 100644 .changeset/multiselect-group-label-3975.md delete mode 100644 .changeset/nav-canonical-metadata-routes-3660.md delete mode 100644 .changeset/nav-sys-objects-canonical-route-3739.md delete mode 100644 .changeset/navigation-items-required-3987.md delete mode 100644 .changeset/no-app-component-metadata-routes-3610.md delete mode 100644 .changeset/no-apps-create-first-app-cta-3573.md delete mode 100644 .changeset/no-apps-go-to-settings-target-3590.md delete mode 100644 .changeset/objectstack-family-rc5-refresh.md delete mode 100644 .changeset/objectview-value-language-3582.md delete mode 100644 .changeset/olive-donkeys-repeat.md delete mode 100644 .changeset/organization-namespace-slice-two.md delete mode 100644 .changeset/os5994-context-selector-persist-enforce.md delete mode 100644 .changeset/outbound-agent-conversation-language-3896.md delete mode 100644 .changeset/page-block-inspector-chrome-i18n.md delete mode 100644 .changeset/page-block-inspector-curated-label-i18n-3913.md delete mode 100644 .changeset/page-header-is-container-3900.md delete mode 100644 .changeset/percent-cell-value-over-bar-os5066.md delete mode 100644 .changeset/pivot-compare-stacking-3614.md delete mode 100644 .changeset/plan-building-label-ui-locale-3837.md delete mode 100644 .changeset/plugin-map-drop-module-scope-console-log-7139.md delete mode 100644 .changeset/plugin-report-react-19-peer-3690.md delete mode 100644 .changeset/predicate-input-template-double-wrap-3871.md delete mode 100644 .changeset/predicate-scope-converge-3955-3957-3960.md delete mode 100644 .changeset/pseudo-route-segment-flags-3638.md delete mode 100644 .changeset/quiet-doors-forward-bodyextra.md delete mode 100644 .changeset/quiet-moons-inherit.md delete mode 100644 .changeset/quota-error-envelope-3491.md delete mode 100644 .changeset/raw-key-call-sites-slice-one.md delete mode 100644 .changeset/react-runtime-peer-upper-bound-3741.md delete mode 100644 .changeset/reclaim-natural-gesture-names-3363.md delete mode 100644 .changeset/record-details-sections-description-3807.md delete mode 100644 .changeset/record-details-sections-name-anchor-3819.md delete mode 100644 .changeset/record-header-manual-refresh-3460.md delete mode 100644 .changeset/registry-inputs-spec-parity-gate-3797.md delete mode 100644 .changeset/related-list-add-picker-filter-3831.md delete mode 100644 .changeset/related-list-add-picker-guard-3838.md delete mode 100644 .changeset/related-list-filter-and-add-gate.md delete mode 100644 .changeset/remaining-setup-links-3611.md delete mode 100644 .changeset/residue-locale-keys-3546-slice7.md delete mode 100644 .changeset/row-action-declared-visible-gate-3758.md delete mode 100644 .changeset/row-action-inline-slot-survivors-3762.md delete mode 100644 .changeset/rowactionmenu-empty-guard.md delete mode 100644 .changeset/runner-preserve-query-on-navigate.md delete mode 100644 .changeset/runner-vite-alias-transitive-closure.md delete mode 100644 .changeset/schemaform-visiblewhen-os6331.md delete mode 100644 .changeset/select-multiple-widget-mapping-3986.md delete mode 100644 .changeset/sour-clouds-yawn.md delete mode 100644 .changeset/system-hub-count-error-state-3679.md delete mode 100644 .changeset/system-hub-org-count-3670.md delete mode 100644 .changeset/system-hub-permissions-leg-3655.md delete mode 100644 .changeset/system-hub-routes-3655.md delete mode 100644 .changeset/timeline-line-items-filter-sort-limit-7137.md delete mode 100644 .changeset/user-filters-button-type-os6952.md delete mode 100644 .changeset/userfilters-allowaddtab-session-tabs-os5236.md delete mode 100644 .changeset/view-edit-wire-gate-5316.md delete mode 100644 .changeset/view-overrides-readback.md delete mode 100644 .changeset/view-readonly-tooltip-semantics-3625.md delete mode 100644 .changeset/view-translation-keys-bare-only-3502.md diff --git a/.changeset/action-bar-member-declared-visible-gate-3823.md b/.changeset/action-bar-member-declared-visible-gate-3823.md deleted file mode 100644 index 18e5625900..0000000000 --- a/.changeset/action-bar-member-declared-visible-gate-3823.md +++ /dev/null @@ -1,47 +0,0 @@ ---- -"@object-ui/components": patch ---- - -`action:bar` member actions declaring `visible: false` are now hidden instead of rendered - -`action:button` and `action:icon` carried the same truthiness gate objectui#3812 -removed from the member-action leaves — `if (schema.visible && !isVisible) -return null` — so `visible: false`, the most explicit way an author can say -"never show this", fell into the "no gate declared" branch and the action -rendered anyway. - -objectui#3812's triage judged the five component-level `schema.visible` gates a -dormant defensive layer, because `packages/react`'s `SchemaRenderer` evaluates -`newSchema.visible !== undefined` and hides the node before the component ever -mounts. Two of the five are not dormant, and this is the difference: - -`action:bar` does not route through `SchemaRenderer`. It resolves each member's -renderer from the `ComponentRegistry` itself and spreads the whole member action -onto that renderer's schema, so an author's `visible` on a member arrives as the -child's own `schema.visible` and lands on the child's gate. `action:bar` is also -the only gate on that path by design — its `filteredActions` deliberately -filters on `requiredPermissions` and `actionRendersAt` only, leaving `visible` to -the member renderer. The path is reachable end-to-end and is now pinned that way -(registry-mounted `action:bar`, member declaring `visible: false`), so the -reachability does not have to be argued again. - -Both gates now read the same named definition as the rest of the family, -`hasDeclaredVisibilityGate` (`!= null && !== ''`) — the invariant objectui#3492 -established for the selection bar and objectui#3758 applied to the row-action -surfaces. The evaluation entry is untouched and already short-circuits a boolean -rather than handing it to the CEL engine, which `actionPredicate.parity` pins for -both the engine and the renderer path. - -Behaviour change surface, deliberately narrow: only an `action:button` / -`action:icon` whose `visible` is the literal boolean `false` (or another falsy -non-empty value) changes — from rendered to hidden, which is what the -declaration asked for. `visible: true` still renders, `''` and an absent -`visible` are still no gate at all, and no expression-valued `visible` changes -verdict. `ActionSchema.visible` is `ExpressionInputSchema` with no boolean -member, so `objectstack build` cannot emit this shape; hand-written view JSON and -in-process callers constructing action defs can. - -The remaining three component-level gates (`action:group`, `action:menu`, -`action:bar`'s own) stay as they are — they only ever mount through -`SchemaRenderer`, which resolves `visible` first, and the overflow `action:menu` -that `action:bar` synthesizes carries no `visible` at all. diff --git a/.changeset/action-declared-disabled-gate-3842.md b/.changeset/action-declared-disabled-gate-3842.md deleted file mode 100644 index 57d743d7c7..0000000000 --- a/.changeset/action-declared-disabled-gate-3842.md +++ /dev/null @@ -1,52 +0,0 @@ ---- -"@object-ui/app-shell": patch -"@object-ui/components": patch ---- - -An action declaring `disabled: ''` is no longer greyed out forever (objectui#3842) - -The "is a `disabled` gate declared?" test stopped at `!= null`, missing the -`!== ''` half of the invariant the `visible` family converged on -(`hasDeclaredVisibilityGate`, objectui#3492 / #3758 / #3812 / #3823 / #3835). So -`disabled: ''` counted as a declared gate, and the verdict went to the evaluation -entry — which reads an empty predicate as "no condition → `true`" -(`toPredicateInput('')` is `undefined`, `evaluateCondition(undefined)` is `true`). - -The direction is why this half is a defect and the `visible` half was not. On -`visible`, that `true` means SHOW, so an over-broad "declared" test and a -permissive empty predicate cancel out and `visible: ''` renders either way. On -`disabled`, the same `true` means DISABLE — the two mistakes compound, and an -empty predicate stopped meaning "no gate" and started meaning "permanently -greyed out". One empty predicate, opposite treatment under two keys. - -Two gates now ask the shared definition instead: - -- `@object-ui/app-shell`'s `DeclaredActionsBar` — the hot one. Its actions are - SERVER-declared (`objectDef.actions[]`) and its hosts are the approvals inbox's - record sections, so a `disabled: ''` arriving from metadata (an authoring form - left empty, a template that rendered to an empty string) produced an Approve / - Reject button nobody could click, indistinguishable from deliberate metadata. - objectui#3835 was this same surface failing the other way. -- `@object-ui/components`' `action:button` — verified to be the same shape before - it was changed (the issue inferred it from the identical spelling but did not - probe it): with `disabled: ''` the rendered button carried `disabled=""`. - -**Behaviour change surface, deliberately narrow.** Only `disabled: ''` changes — -from disabled to clickable, which is what "no predicate" asked for. `disabled: -true` still disables, `disabled: false` and an absent `disabled` still do not, and -no expression-valued `disabled` changes verdict. One consequence worth naming: on -`action:button`, an empty `disabled` now falls THROUGH to the legacy non-spec -`enabled` fallback instead of short-circuiting on the empty predicate, so an -action spelling both (`disabled: ''` + `enabled: true`) becomes clickable. - -The legacy `enabled` leg of `action:button` was routed through the same -definition for consistency, and that part is behaviour-preserving by derivation -rather than a fix: the leg is negated (`disabled = !isEnabled`), so an empty -predicate's `true` already arrived as "not disabled" — the same verdict "no gate" -produces. All four shapes are identical under either test; the derivation table -and the reason no test can distinguish them are written down next to the pins. - -`hasDeclaredVisibilityGate` keeps its historic name at both call sites (the -objectui#3842 dispatch ruling): the predicate is key-neutral, and one -implementation behind two names is how a repo grows dialects. Each call site says -so in a comment. diff --git a/.changeset/action-member-declared-disabled-gate-3849.md b/.changeset/action-member-declared-disabled-gate-3849.md deleted file mode 100644 index f66b66875c..0000000000 --- a/.changeset/action-member-declared-disabled-gate-3849.md +++ /dev/null @@ -1,50 +0,0 @@ ---- -"@object-ui/components": patch -"@object-ui/plugin-detail": patch ---- - -`disabled: ''` no longer greys out the remaining five action surfaces (objectui#3849) - -objectui#3842 / PR #3851 fixed the "is a `disabled` gate DECLARED?" test on -`action:button` and app-shell's `DeclaredActionsBar`. Five same-shaped sites were -outside that PR's scope and stayed on `!= null`, so within one component the -`visible` gate asked `hasDeclaredVisibilityGate` while the `disabled` gate on the -next line asked `!= null` — two spellings of one question: - -- `@object-ui/components` — `action:icon`, `action:group`'s inline button - (`InlineActionButton`) and dropdown item (`DropdownActionItem`), and - `action:menu`'s item (`ActionMenuItem`). -- `@object-ui/plugin-detail` — `record:quick_actions`' `QuickActionButton`. - -Why the missing `!== ''` half is a defect on this key and not on `visible`: -`toPredicateInput('')` is `undefined` and `evaluateCondition(undefined)` is -`true`. On `visible` that `true` means SHOW, so an over-broad "declared" test and -a permissive empty predicate cancel out. On `disabled` it means DISABLE, so they -compound — `disabled: ''` (an empty predicate: nothing declared) rendered a -permanently greyed-out control, with nothing the author could write to un-grey -it. Unlike #3842's approvals inbox, these five are the general action face -(toolbars, dropdowns, record quick actions), so the reach is wider even though no -single high-value host owns them. - -**Behaviour change surface, deliberately narrow.** Only `disabled: ''` changes — -from disabled to clickable, which is what "no predicate" asked for. `disabled: -true` still disables, `disabled: false` and an absent `disabled` still do not, and -no expression-valued `disabled` changes verdict. On the four sites that also carry -the legacy non-spec `enabled` fallback, one consequence follows: an empty -`disabled` now falls THROUGH to that leg instead of short-circuiting on the empty -predicate, so an action spelling both (`disabled: ''` + `enabled: true`) becomes -clickable. `record:quick_actions` has no `enabled` leg, so its chain is the single -gate. - -Routing those legacy `enabled` legs through the same definition is -behaviour-preserving by derivation rather than a fix: the leg is negated -(`disabled = !isEnabled`), so an empty predicate's `true` already arrived as "not -disabled" — the verdict "no gate declared" produces. #3842's four-shape derivation -table is reproduced next to the new pins, together with the statement that no -`enabled` case can go red by reverting that leg. - -`hasDeclaredVisibilityGate` keeps its historic name (the objectui#3842 ruling): the -predicate is key-neutral, and one implementation behind two names is how a repo -grows dialects. The three `@object-ui/components` sites import it relatively; -`record:quick_actions` takes it from the package barrel, the cross-package route -objectui#3835 opened. Every call site says so in a comment. diff --git a/.changeset/action-member-declared-visible-gate-3812.md b/.changeset/action-member-declared-visible-gate-3812.md deleted file mode 100644 index e0de1e891c..0000000000 --- a/.changeset/action-member-declared-visible-gate-3812.md +++ /dev/null @@ -1,37 +0,0 @@ ---- -"@object-ui/components": patch ---- - -Action-face member actions declaring `visible: false` are now hidden instead of rendered - -The three member-action gates on the action face asked truthiness — -`if (action.visible && !isVisible) return null` — so `visible: false`, the most -explicit way an author can say "never show this", fell into the "no gate -declared" branch and the action rendered anyway: - -- `action:group` in `display: 'inline'` mode (`InlineActionButton`); -- `action:group` in `display: 'dropdown'` mode (`DropdownActionItem`); -- `action:menu`'s items (`ActionMenuItem`). - -These leaves `.map()` the component's own `actions` array, so neither -`SchemaRenderer`'s node-level `visible` handling nor -`ActionEngine.getActionsForLocation` (whose boolean `visible` was always -correct) is in the path — the truthy gate was the only gate. - -All three now read one named definition, `hasDeclaredVisibilityGate` -(`!= null && !== ''`), and let the declaration itself decide. This is not a new -decision: objectui#3492 established the invariant for the selection bar, whose -`hasVisibilityGate` spells out why truthiness cannot answer the question, and -objectui#3758 applied it to both row-action surfaces. The evaluation entry is -untouched and already short-circuits a boolean rather than handing it to the CEL -engine, which `actionPredicate.parity` pins for both the engine and the renderer -path. - -Behaviour change surface, deliberately narrow: only a member action whose -`visible` is the literal boolean `false` (or another falsy non-empty value) -changes — from rendered to hidden, which is what the declaration asked for. -`visible: true` still renders, `''` and an absent `visible` are still no gate at -all, and no expression-valued `visible` changes verdict. -`ActionSchema.visible` is `ExpressionInputSchema` with no boolean member, so -`objectstack build` cannot emit this shape; hand-written view JSON and -in-process callers constructing action defs can. diff --git a/.changeset/action-param-datetime-zoned-instant-os5061.md b/.changeset/action-param-datetime-zoned-instant-os5061.md deleted file mode 100644 index f916e31a90..0000000000 --- a/.changeset/action-param-datetime-zoned-instant-os5061.md +++ /dev/null @@ -1,55 +0,0 @@ ---- -"@object-ui/app-shell": patch ---- - -`datetime` action params are usable in the Console for the first time — the dialog now POSTs the zoned ISO instant the platform requires instead of a shape the validator rejects - -An action declaring a `type: 'datetime'` param was unusable from the UI: **no -value a user could pick could pass validation**. The dialog rendered the param -as `datetime-local` (which is zone-less by nature) and then serialized on -submit back to that control's own naive wall clock, e.g. `2026-08-10T15:00`. -Since 17.0 the dispatcher validates a params bag against the action's -declaration before the handler runs (ADR-0104 D2, `validateActionParams` → -`InstantValueSchema`), and that contract is an ISO-8601 instant with an -explicit zone. Every submission earned: - -``` -HTTP 400 VALIDATION_ERROR -Action param "start" (datetime): expected an ISO-8601 instant with explicit -zone (e.g. 2026-03-15T14:30:00.000Z) -``` - -The renderer and the validator wanted disjoint shapes, and an app author had no -seam between them — declaring a `datetime` param doomed the action in the UI, -whatever the app. Found in a hotcrm dogfood run (objectstack#5061), reproduced -from two separate entry points (list-view row menu and record header). - -The fix is a removal, not a conversion. `DateTimeField` has been ISO-canonical -on both sides since objectui#3127/#3565 — it takes the record's ISO instant in -and hands an ISO instant back out, seconds, milliseconds and zone included — so -the widget's own value already satisfies the contract. #3565 added the -back-conversion to keep the wire shape byte-identical while it fixed a display -bug, and named the follow-up in its own commit message: moving action params -onto ISO is a contract change of its own. This is that change. -`serializeParamValues` now passes `datetime` values through untouched, which -makes it idempotent for a value that already carries a zone (a `+08:00` offset -survives byte-for-byte rather than being re-derived and re-cut to the minute) -and leaves an empty or unfilled param alone. - -Deliberately still rejected: an authored `defaultValue` written as a zone-less -wall clock. That value is ambiguous metadata — whose zone? — and coercing it in -the renderer would make it "work" in the UI while the identical literal kept -400ing from REST and MCP, which is the worst split to debug. It stays loud -until the spec validates a param default against the param's own value -contract, filed as objectstack#6970 (the same hole lets a `number` param -default to `'abc'`, so it is not datetime-specific). - -The render proof that pinned the old shape was replaced rather than re-spelled: -it asserted `2026-07-20T14:30` and was green while the feature was 100% broken, -because the shape it pinned is the one shape nothing accepts. It now drives the -real widget and asks the real `validateActionParams` — the exact function that -produced the 400 — whether the resolved bag is acceptable. The datetime -assertions are written to hold in every timezone (verified under -`Asia/Shanghai`, `UTC` and `America/Los_Angeles`), since a zone-shaped test that -only holds in UTC goes green on CI while the defect is live for every user east -or west of it. diff --git a/.changeset/action-runner-declared-condition-gate-3872.md b/.changeset/action-runner-declared-condition-gate-3872.md deleted file mode 100644 index 74393aa77f..0000000000 --- a/.changeset/action-runner-declared-condition-gate-3872.md +++ /dev/null @@ -1,59 +0,0 @@ ---- -"@object-ui/core": patch ---- - -`condition: false` now actually prevents the action from executing (objectui#3872) - -`ActionRunner.execute` — the engine's public execution entry, shared by every -action surface — gated conditional execution on `if (action.condition)`, i.e. on -the raw value's TRUTHINESS. Truthiness cannot answer the question the gate needs -answered ("did the author declare a condition?"), and on this key it answered in -the over-permissive direction: `condition: false` fell on `if (false)`, so the -whole block was skipped, `evaluateCondition` was never consulted, and the action -executed. Measured with a call-counting handler: - -- `condition: false` — handler ran: **true**, result `{ success: true }` -- `condition: { dialect: 'cel', source: 'false' }` — handler ran: false, result `{ success: false, error: 'Action condition not met' }` - -Two spellings of the same statement, opposite outcomes. `false` is the most -explicit "never execute this" metadata can carry — and what a template that -switches an action off emits — so the direction matters: the action really ran, -possibly writing. This is the over-permission half of the objectui#3492 family -(the `disabled` gate one line below is objectui#3848, whose defect pointed the -other way). - -The gate now asks whether a `condition` gate is DECLARED before evaluating. -"Nothing to evaluate" is read from core's single predicate normalizer -(`toPredicateInput`, which maps `''`, `null`, an empty-`source` envelope and -non-predicate values to `undefined`), plus the whitespace-only string, which the -normalizer wraps rather than collapses — objectui#3850's ruling on the scope of -"empty predicate", the same one the `disabled` gate already applies. Once the -door asks the right question the verdict needs no boolean branch of its own: -`evaluateCondition` returns a boolean argument verbatim. - -**Behaviour change surface, deliberately one-directional and one row wide.** -Exactly one shape changes verdict — a declared boolean `false`, from executing to -refused (`{ success: false, error: 'Action condition not met' }`, the message the -key already used). Everything else is byte-identical: `condition: true`, an -absent `condition`, and truthy expressions/envelopes still execute; falsy -expressions, falsy CEL envelopes and falsy `${…}` templates are still refused, -as before; the three empty predicates (`''`, whitespace-only, an empty-`source` -envelope) still execute, now because nothing was declared rather than because -`if ('')` happened to be falsy; and non-predicate junk (`0`, `{}`) still -executes — a value that is not a predicate must not decide an action's fate, -which is the fail-open posture this module already committed to for `disabled`. -So this change can only start refusing execution, never start allowing it — the -mirror image of objectui#3848's fix. - -`ActionDef.condition` is widened to `string | boolean` to match what the gate now -honours (and the `disabled` key beside it). This is not a lenient consumer -alias: the boolean was always accepted at runtime through the interface's index -signature, it was simply ignored. - -The value handed to the evaluator is deliberately left RAW rather than normalized -first, for the same reason as objectui#3848 with the sign flipped: -`toPredicateInput` wraps unconditionally, so an already-templated `'${x}'` -becomes `'${${x}}'`, fails to parse, returns verbatim and coerces to a constant -`true` — on `disabled` that blocks everything, on `condition` it would EXECUTE -everything. That normalizer defect is objectui#3871; a tripwire next to the new -pins goes red the day it is fixed. diff --git a/.changeset/action-runner-declared-disabled-gate-3848.md b/.changeset/action-runner-declared-disabled-gate-3848.md deleted file mode 100644 index 3690491dd6..0000000000 --- a/.changeset/action-runner-declared-disabled-gate-3848.md +++ /dev/null @@ -1,54 +0,0 @@ ---- -"@object-ui/core": patch ---- - -An empty `disabled` predicate no longer refuses to run the action (objectui#3848) - -`ActionRunner.execute` — the engine's public execution entry, shared by every -action surface — gated on `action.disabled != null && action.disabled !== false` -and handed the value straight to `evaluateCondition`. That function documents one -default for "there is no condition here": return `true`, meaning -*visible/enabled*. On `disabled`, `true` means BLOCKED. So every empty predicate -was read as "disabled": the handler was never invoked and the caller got -`{ success: false, error: 'Action is disabled' }` — a state the metadata never -declared. Measured with a call-counting handler: - -- `disabled: ''` — handler ran: false -- `disabled: ' '` (whitespace only) — handler ran: false -- `disabled: { dialect: 'cel', source: '' }` (the empty envelope `objectstack build` can emit) — handler ran: false - -After objectui#3842 / objectui#3849 fixed the renderer halves, this was live -user-visible behaviour: the button became clickable and clicking it returned -`Action is disabled` — the renderer and the execution entry disagreeing about one -predicate value, the shape objectui#3314 already paid for once. - -The gate now asks whether a `disabled` gate is DECLARED — whether there is a -condition to reach a verdict on — before evaluating. "Nothing to evaluate" is -read from core's single predicate normalizer (`toPredicateInput`, which maps -`''`, `null`, an empty-`source` envelope and non-predicate values to -`undefined`), plus the whitespace-only string, which the normalizer wraps rather -than collapses and which `evaluateCondition` itself calls "no condition" -(`evalRowPredicate` applies the same blank-source rule). - -**Behaviour change surface, deliberately one-directional.** Only values with -nothing to evaluate change, and only from blocked to allowed: `''`, -whitespace-only, an empty-`source` envelope, and non-predicate junk (`0`, `{}`, -which previously coerced to "disabled"). `disabled: true`, a truthy expression -and a truthy CEL envelope still block; `disabled: false` and an absent `disabled` -still run; no expression- or envelope-valued predicate changes verdict. The -existing `catch { isDisabled = false }` fail-open posture is untouched, and this -change can only stop blocking things, never start. - -The value handed to the evaluator is deliberately left RAW rather than normalized -first. `evaluateCondition(toPredicateInput(x))` is not interchangeable with -`evaluateCondition(x)` for a string that is already a `${…}` template: -`toPredicateInput` assumes a bare expression and wraps unconditionally, so -`'${x}'` becomes `'${${x}}'`, fails to parse, returns verbatim, and coerces to a -constant `true` — a template-spelled predicate evaluated that way is ALWAYS -"disabled", whatever it says. That normalizer defect is filed as objectui#3871 -(it is live at the action renderers and `ActionEngine`, while `SchemaRenderer` and -`page:header` evaluate the raw value and pin the correct verdict); a tripwire next -to the new pins goes red the day it is fixed. Two rows therefore still differ -between the execution and renderer paths, each recorded with its owning issue: -the empty envelope (objectui#3850 owns the renderer half's scope ruling) and the -`${…}` spelling (objectui#3871). diff --git a/.changeset/actionparamdialog-boolean-host-id-3962.md b/.changeset/actionparamdialog-boolean-host-id-3962.md deleted file mode 100644 index 317015767d..0000000000 --- a/.changeset/actionparamdialog-boolean-host-id-3962.md +++ /dev/null @@ -1,30 +0,0 @@ ---- -"@object-ui/app-shell": patch ---- - -`ActionParamDialog` boolean params: the dialog now owns the control id, so the checkbox is named once instead of twice - -The boolean branch rendered `