From 046854b8723fdae9f732befb19b9882d7deb4c96 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 12 Aug 2026 11:37:40 +0000 Subject: [PATCH] chore: release packages --- .../accept-invitation-single-route-3811.md | 15 - .../action-confirm-text-translation-4265.md | 25 - ...tion-forward-whitelist-parity-4050-4192.md | 13 - .../action-menu-autotrigger-overflow-4162.md | 13 - .../action-typing-integrity-4418-4422.md | 18 - .../actiondef-close-the-index-signature.md | 51 -- .changeset/address-display-formatter-4037.md | 15 - ...ild-thread-survives-preview-switch-2627.md | 15 - .../aichatpage-runtime-message-seam-4437.md | 13 - .../analytics-label-net-shared-glue-4389.md | 16 - .../analytics-option-label-i18n-4030.md | 17 - .../api-console-storage-slot-key-4240.md | 11 - .changeset/app-management-page-i18n-4307.md | 35 - .../app-management-search-keyed-label-4343.md | 19 - .../autonumber-textual-ref-fallback-4219.md | 13 - .../bell-approvals-activity-off-app-4197.md | 13 - .changeset/bell-panel-render-oracle-4230.md | 20 - .../bridge-density-prototype-guard-4442.md | 24 - .changeset/button-has-type-lint-4045.md | 23 - .changeset/calm-schools-tease.md | 22 - .changeset/chatmessage-one-contract-4383.md | 11 - .changeset/chatmessage-seam-adapter.md | 20 - ...bo-dataset-path-presentation-merge-4229.md | 17 - .../commit-store-unreachable-copy-3529.md | 14 - .changeset/components-no-implicit-any-4353.md | 17 - .../components-type-checks-its-tests.md | 12 - .../core-app-shell-type-check-their-tests.md | 16 - .../currency-iso-4217-minor-units-4361.md | 49 - .changeset/curvy-donkeys-shave.md | 22 - ...ta-table-row-menu-predicate-derive-4354.md | 11 - .../dataset-result-field-derive-3815.md | 11 - ...widget-option-color-probe-apifetch-4121.md | 24 - ...tasource-preview-strict-key-groups-4131.md | 24 - .changeset/dead-currency-symbol-map.md | 18 - .../dead-surface-deletions-batch3-4328.md | 40 - .changeset/dead-surface-pair-4364-4368.md | 39 - ...clared-actions-bar-drop-predicate-casts.md | 18 - ...lared-actions-bar-predicate-helper-4080.md | 11 - ...lt-app-landing-and-real-app-writes-4233.md | 15 - .changeset/designer-table-ellipsis-4377.md | 15 - .../designer-table-key-collapse-4387.md | 20 - ...otted-dimension-labels-table-pivot-4263.md | 28 - .../dotted-dimension-option-labels-4053.md | 19 - ...tton-forward-excess-property-check-4321.md | 15 - ...ment-deeplink-arm-on-create-action-4123.md | 13 - .changeset/fields-subpath-surface-4325.md | 35 - .../filter-panel-no-view-overlay-4155.md | 17 - .changeset/form-route-edit-recordid-4278.md | 16 - .changeset/fullscreen-editor-hoist-3398.md | 18 - .changeset/gantt-count-interpolation-4157.md | 14 - .../gantt-link-rejection-feedback-4158.md | 16 - .../gated-options-keep-stored-value-4247.md | 14 - .changeset/global-filter-preset-alias-4165.md | 15 - .changeset/global-nav-studio-retire-rc6.md | 35 - .changeset/great-mails-repeat.md | 9 - ...d-bulk-bar-clear-resets-checkboxes-4140.md | 9 - .../grid-row-menu-predicate-derive-4429.md | 13 - .../handrolled-interpolators-literal-4370.md | 23 - ...on-centre-badges-full-unread-count-4329.md | 15 - ...home-action-centre-needs-an-answer-4235.md | 26 - .../host-app-resolver-root-export-4280.md | 14 - .changeset/i18n-copy-trio-3878-3875-3877.md | 27 - .changeset/i18n-stragglers-4375-4376.md | 23 - .changeset/i18nlabel-render-sites-4163.md | 26 - .changeset/image-field-maxsize-guard-4141.md | 13 - .../inbox-activity-links-host-app-4074.md | 15 - .../inbox-popover-bell-polls-off-app-4110.md | 14 - .changeset/init-scaffold-vite-env-tsc-4111.md | 11 - .changeset/inline-address-input-4216.md | 15 - .changeset/inline-credential-gate-4221.md | 15 - .../inline-default-value-drift-gate-3810.md | 39 - .changeset/inline-edit-delegate-4220.md | 33 - .changeset/internal-form-in-shell-4109.md | 13 - .changeset/interpolation-parity-gate-3845.md | 19 - .../kanban-rejected-move-rollback-4138.md | 13 - .changeset/list-filtered-empty-copy-4155.md | 11 - ...list-sort-field-fallback-and-reset-4243.md | 14 - .../listview-shared-datasource-gate-4038.md | 47 - .../local-select-dimension-i18n-4330.md | 14 - .changeset/locale-menu-from-app-4039.md | 17 - .changeset/lucky-buttons-shave.md | 13 - .changeset/map-pack-mirror-gate-4401.md | 18 - ...apdensity-dead-rowheight-spellings-4352.md | 36 - .changeset/metric-kpi-i18n-channel-4032.md | 45 - .../metric-props-dom-passthrough-4426.md | 20 - .changeset/metric-widget-dom-spread-4357.md | 47 - .changeset/nervous-pans-repeat.md | 33 - ...ber-format-locale-ordinal-grouping-4033.md | 20 - .../objectchart-label-net-third-copy-4405.md | 13 - ...tchart-option-color-probe-apifetch-4114.md | 21 - ...jectgrid-external-pagination-props-4277.md | 13 - .../objectgrid-rowheight-boundary-4443.md | 18 - .changeset/objectmap-filter-config-4034.md | 15 - .changeset/olive-donkeys-shake.md | 22 - .changeset/olive-eels-shave.md | 8 - .changeset/phantom-dependency-gate-4394.md | 11 - .changeset/picklocalized-own-props-3907.md | 11 - .changeset/pivot-null-bucket-4056.md | 50 -- .changeset/react-type-checks-its-tests.md | 10 - ...record-details-retire-layout-input-3818.md | 15 - .changeset/record-picker-filter-input-3830.md | 41 - ...ecord-picker-sort-limit-empty-text-4167.md | 46 - .../render-save-advisory-findings-4133.md | 17 - .../required-when-submit-verdict-4161.md | 11 - .../reserved-auth-feature-flags-2514.md | 15 - ...retire-action-engine-event-mapping-3368.md | 25 - .../retire-cloud-operations-surface-4152.md | 71 -- .changeset/retire-common-search-key-4392.md | 43 - .../retire-narrow-typetests-projects-4291.md | 12 - .../retire-object-detail-factory-3731-3736.md | 11 - .../retire-report-editor-namespace-4145.md | 31 - ...ire-standalone-validation-resource-4132.md | 60 -- .../retire-url-action-params-newtab-4097.md | 11 - .changeset/richtext-spec-spelling-4250.md | 15 - .changeset/rotten-plums-smash.md | 6 - .../rowheight-density-one-answer-4440.md | 42 - .../safe-translation-inline-default-3865.md | 22 - .../second-client-save-advisories-4237.md | 14 - .../set-default-view-tab-identity-4211.md | 15 - .changeset/setup-deep-link-2794.md | 18 - .../setup-exit-console-basename-4181.md | 13 - .changeset/shared-inbox-feed-4225.md | 35 - ...show-empty-related-plural-base-key-3863.md | 14 - .../sidebar-collapse-survives-reload-4234.md | 15 - .changeset/six-bare-keys-defaults-4396.md | 11 - .../sort-relational-hint-stored-field-4294.md | 12 - .changeset/spec-symbol-collisions-rc6-4167.md | 92 -- .../sso-landing-setup-only-home-4048.md | 36 - .changeset/studio-dock-polish-pins.md | 10 - .../studio-readonly-affordances-4036.md | 15 - .../synth-page-canonical-properties-4232.md | 28 - .changeset/tall-eagles-repeat.md | 21 - .../tenant-locale-seeds-ui-language-4035.md | 34 - .changeset/tidy-eels-invite.md | 27 - .changeset/type-check-tests-auth-4040.md | 16 - .changeset/type-check-tests-i18n-4040.md | 32 - .../type-check-tests-permissions-4040.md | 15 - .../type-check-tests-plugin-chatbot-4040.md | 21 - .../type-check-tests-plugin-form-4040.md | 28 - .../type-check-tests-plugin-gantt-4040.md | 19 - .../type-check-tests-plugin-map-4040.md | 16 - ...ished-banner-reads-unpublished-key-6955.md | 18 - .../updateview-draft-addressing-4139.md | 13 - .../useobjectchat-honest-message-type-4424.md | 16 - .changeset/view-invalidation-seam-4373.md | 14 - .../view-overrides-invalidation-4363.md | 13 - .changeset/widget-dom-leak-sweep-gate-4425.md | 29 - .changeset/wild-pugs-smoke.md | 5 - .changeset/wise-pumas-attack.md | 19 - .changeset/wrong-slot-i18n-keys-4118.md | 15 - apps/console/CHANGELOG.md | 335 +++++++ apps/console/package.json | 2 +- packages/app-shell/CHANGELOG.md | 835 ++++++++++++++++++ packages/app-shell/package.json | 2 +- packages/auth/CHANGELOG.md | 24 + packages/auth/package.json | 2 +- packages/cli/CHANGELOG.md | 52 ++ packages/cli/package.json | 2 +- packages/collaboration/CHANGELOG.md | 48 + packages/collaboration/package.json | 2 +- packages/components/CHANGELOG.md | 418 +++++++++ packages/components/package.json | 2 +- packages/core/CHANGELOG.md | 430 +++++++++ packages/core/package.json | 2 +- packages/create-plugin/CHANGELOG.md | 2 + packages/create-plugin/package.json | 2 +- packages/data-objectstack/CHANGELOG.md | 179 ++++ packages/data-objectstack/package.json | 2 +- packages/fields/CHANGELOG.md | 389 ++++++++ packages/fields/package.json | 2 +- packages/i18n/CHANGELOG.md | 313 +++++++ packages/i18n/package.json | 2 +- packages/layout/CHANGELOG.md | 147 +++ packages/layout/package.json | 2 +- packages/mobile/CHANGELOG.md | 12 + packages/mobile/package.json | 2 +- packages/permissions/CHANGELOG.md | 48 + packages/permissions/package.json | 2 +- packages/plugin-ai/CHANGELOG.md | 55 ++ packages/plugin-ai/package.json | 2 +- packages/plugin-calendar/CHANGELOG.md | 101 +++ packages/plugin-calendar/package.json | 2 +- packages/plugin-charts/CHANGELOG.md | 116 +++ packages/plugin-charts/package.json | 2 +- packages/plugin-chatbot/CHANGELOG.md | 101 +++ packages/plugin-chatbot/package.json | 2 +- packages/plugin-dashboard/CHANGELOG.md | 355 ++++++++ packages/plugin-dashboard/package.json | 2 +- packages/plugin-designer/CHANGELOG.md | 224 +++++ packages/plugin-designer/package.json | 2 +- packages/plugin-detail/CHANGELOG.md | 246 ++++++ packages/plugin-detail/package.json | 2 +- packages/plugin-editor/CHANGELOG.md | 44 + packages/plugin-editor/package.json | 2 +- packages/plugin-form/CHANGELOG.md | 80 ++ packages/plugin-form/package.json | 2 +- packages/plugin-gantt/CHANGELOG.md | 122 +++ packages/plugin-gantt/package.json | 2 +- packages/plugin-grid/CHANGELOG.md | 149 ++++ packages/plugin-grid/package.json | 2 +- packages/plugin-kanban/CHANGELOG.md | 118 +++ packages/plugin-kanban/package.json | 2 +- packages/plugin-list/CHANGELOG.md | 216 +++++ packages/plugin-list/package.json | 2 +- packages/plugin-map/CHANGELOG.md | 67 ++ packages/plugin-map/package.json | 2 +- packages/plugin-markdown/CHANGELOG.md | 44 + packages/plugin-markdown/package.json | 2 +- packages/plugin-report/CHANGELOG.md | 140 +++ packages/plugin-report/package.json | 2 +- packages/plugin-timeline/CHANGELOG.md | 63 ++ packages/plugin-timeline/package.json | 2 +- packages/plugin-tree/CHANGELOG.md | 62 ++ packages/plugin-tree/package.json | 2 +- packages/plugin-view/CHANGELOG.md | 81 ++ packages/plugin-view/package.json | 2 +- packages/providers/CHANGELOG.md | 12 + packages/providers/package.json | 2 +- packages/react-runtime/CHANGELOG.md | 2 + packages/react-runtime/package.json | 2 +- packages/react/CHANGELOG.md | 261 ++++++ packages/react/package.json | 2 +- packages/runner/CHANGELOG.md | 60 ++ packages/runner/package.json | 2 +- packages/sdui-parser/CHANGELOG.md | 2 + packages/sdui-parser/package.json | 2 +- packages/types/CHANGELOG.md | 234 +++++ packages/types/package.json | 2 +- packages/vscode-extension/CHANGELOG.md | 23 + packages/vscode-extension/package.json | 2 +- 230 files changed, 6250 insertions(+), 3215 deletions(-) delete mode 100644 .changeset/accept-invitation-single-route-3811.md delete mode 100644 .changeset/action-confirm-text-translation-4265.md delete mode 100644 .changeset/action-forward-whitelist-parity-4050-4192.md delete mode 100644 .changeset/action-menu-autotrigger-overflow-4162.md delete mode 100644 .changeset/action-typing-integrity-4418-4422.md delete mode 100644 .changeset/actiondef-close-the-index-signature.md delete mode 100644 .changeset/address-display-formatter-4037.md delete mode 100644 .changeset/ai-build-thread-survives-preview-switch-2627.md delete mode 100644 .changeset/aichatpage-runtime-message-seam-4437.md delete mode 100644 .changeset/analytics-label-net-shared-glue-4389.md delete mode 100644 .changeset/analytics-option-label-i18n-4030.md delete mode 100644 .changeset/api-console-storage-slot-key-4240.md delete mode 100644 .changeset/app-management-page-i18n-4307.md delete mode 100644 .changeset/app-management-search-keyed-label-4343.md delete mode 100644 .changeset/autonumber-textual-ref-fallback-4219.md delete mode 100644 .changeset/bell-approvals-activity-off-app-4197.md delete mode 100644 .changeset/bell-panel-render-oracle-4230.md delete mode 100644 .changeset/bridge-density-prototype-guard-4442.md delete mode 100644 .changeset/button-has-type-lint-4045.md delete mode 100644 .changeset/calm-schools-tease.md delete mode 100644 .changeset/chatmessage-one-contract-4383.md delete mode 100644 .changeset/chatmessage-seam-adapter.md delete mode 100644 .changeset/combo-dataset-path-presentation-merge-4229.md delete mode 100644 .changeset/commit-store-unreachable-copy-3529.md delete mode 100644 .changeset/components-no-implicit-any-4353.md delete mode 100644 .changeset/components-type-checks-its-tests.md delete mode 100644 .changeset/core-app-shell-type-check-their-tests.md delete mode 100644 .changeset/currency-iso-4217-minor-units-4361.md delete mode 100644 .changeset/curvy-donkeys-shave.md delete mode 100644 .changeset/data-table-row-menu-predicate-derive-4354.md delete mode 100644 .changeset/dataset-result-field-derive-3815.md delete mode 100644 .changeset/datasetwidget-option-color-probe-apifetch-4121.md delete mode 100644 .changeset/datasource-preview-strict-key-groups-4131.md delete mode 100644 .changeset/dead-currency-symbol-map.md delete mode 100644 .changeset/dead-surface-deletions-batch3-4328.md delete mode 100644 .changeset/dead-surface-pair-4364-4368.md delete mode 100644 .changeset/declared-actions-bar-drop-predicate-casts.md delete mode 100644 .changeset/declared-actions-bar-predicate-helper-4080.md delete mode 100644 .changeset/default-app-landing-and-real-app-writes-4233.md delete mode 100644 .changeset/designer-table-ellipsis-4377.md delete mode 100644 .changeset/designer-table-key-collapse-4387.md delete mode 100644 .changeset/dotted-dimension-labels-table-pivot-4263.md delete mode 100644 .changeset/dotted-dimension-option-labels-4053.md delete mode 100644 .changeset/element-button-forward-excess-property-check-4321.md delete mode 100644 .changeset/environment-deeplink-arm-on-create-action-4123.md delete mode 100644 .changeset/fields-subpath-surface-4325.md delete mode 100644 .changeset/filter-panel-no-view-overlay-4155.md delete mode 100644 .changeset/form-route-edit-recordid-4278.md delete mode 100644 .changeset/fullscreen-editor-hoist-3398.md delete mode 100644 .changeset/gantt-count-interpolation-4157.md delete mode 100644 .changeset/gantt-link-rejection-feedback-4158.md delete mode 100644 .changeset/gated-options-keep-stored-value-4247.md delete mode 100644 .changeset/global-filter-preset-alias-4165.md delete mode 100644 .changeset/global-nav-studio-retire-rc6.md delete mode 100644 .changeset/great-mails-repeat.md delete mode 100644 .changeset/grid-bulk-bar-clear-resets-checkboxes-4140.md delete mode 100644 .changeset/grid-row-menu-predicate-derive-4429.md delete mode 100644 .changeset/handrolled-interpolators-literal-4370.md delete mode 100644 .changeset/home-action-centre-badges-full-unread-count-4329.md delete mode 100644 .changeset/home-action-centre-needs-an-answer-4235.md delete mode 100644 .changeset/host-app-resolver-root-export-4280.md delete mode 100644 .changeset/i18n-copy-trio-3878-3875-3877.md delete mode 100644 .changeset/i18n-stragglers-4375-4376.md delete mode 100644 .changeset/i18nlabel-render-sites-4163.md delete mode 100644 .changeset/image-field-maxsize-guard-4141.md delete mode 100644 .changeset/inbox-activity-links-host-app-4074.md delete mode 100644 .changeset/inbox-popover-bell-polls-off-app-4110.md delete mode 100644 .changeset/init-scaffold-vite-env-tsc-4111.md delete mode 100644 .changeset/inline-address-input-4216.md delete mode 100644 .changeset/inline-credential-gate-4221.md delete mode 100644 .changeset/inline-default-value-drift-gate-3810.md delete mode 100644 .changeset/inline-edit-delegate-4220.md delete mode 100644 .changeset/internal-form-in-shell-4109.md delete mode 100644 .changeset/interpolation-parity-gate-3845.md delete mode 100644 .changeset/kanban-rejected-move-rollback-4138.md delete mode 100644 .changeset/list-filtered-empty-copy-4155.md delete mode 100644 .changeset/list-sort-field-fallback-and-reset-4243.md delete mode 100644 .changeset/listview-shared-datasource-gate-4038.md delete mode 100644 .changeset/local-select-dimension-i18n-4330.md delete mode 100644 .changeset/locale-menu-from-app-4039.md delete mode 100644 .changeset/lucky-buttons-shave.md delete mode 100644 .changeset/map-pack-mirror-gate-4401.md delete mode 100644 .changeset/mapdensity-dead-rowheight-spellings-4352.md delete mode 100644 .changeset/metric-kpi-i18n-channel-4032.md delete mode 100644 .changeset/metric-props-dom-passthrough-4426.md delete mode 100644 .changeset/metric-widget-dom-spread-4357.md delete mode 100644 .changeset/nervous-pans-repeat.md delete mode 100644 .changeset/number-format-locale-ordinal-grouping-4033.md delete mode 100644 .changeset/objectchart-label-net-third-copy-4405.md delete mode 100644 .changeset/objectchart-option-color-probe-apifetch-4114.md delete mode 100644 .changeset/objectgrid-external-pagination-props-4277.md delete mode 100644 .changeset/objectgrid-rowheight-boundary-4443.md delete mode 100644 .changeset/objectmap-filter-config-4034.md delete mode 100644 .changeset/olive-donkeys-shake.md delete mode 100644 .changeset/olive-eels-shave.md delete mode 100644 .changeset/phantom-dependency-gate-4394.md delete mode 100644 .changeset/picklocalized-own-props-3907.md delete mode 100644 .changeset/pivot-null-bucket-4056.md delete mode 100644 .changeset/react-type-checks-its-tests.md delete mode 100644 .changeset/record-details-retire-layout-input-3818.md delete mode 100644 .changeset/record-picker-filter-input-3830.md delete mode 100644 .changeset/record-picker-sort-limit-empty-text-4167.md delete mode 100644 .changeset/render-save-advisory-findings-4133.md delete mode 100644 .changeset/required-when-submit-verdict-4161.md delete mode 100644 .changeset/reserved-auth-feature-flags-2514.md delete mode 100644 .changeset/retire-action-engine-event-mapping-3368.md delete mode 100644 .changeset/retire-cloud-operations-surface-4152.md delete mode 100644 .changeset/retire-common-search-key-4392.md delete mode 100644 .changeset/retire-narrow-typetests-projects-4291.md delete mode 100644 .changeset/retire-object-detail-factory-3731-3736.md delete mode 100644 .changeset/retire-report-editor-namespace-4145.md delete mode 100644 .changeset/retire-standalone-validation-resource-4132.md delete mode 100644 .changeset/retire-url-action-params-newtab-4097.md delete mode 100644 .changeset/richtext-spec-spelling-4250.md delete mode 100644 .changeset/rotten-plums-smash.md delete mode 100644 .changeset/rowheight-density-one-answer-4440.md delete mode 100644 .changeset/safe-translation-inline-default-3865.md delete mode 100644 .changeset/second-client-save-advisories-4237.md delete mode 100644 .changeset/set-default-view-tab-identity-4211.md delete mode 100644 .changeset/setup-deep-link-2794.md delete mode 100644 .changeset/setup-exit-console-basename-4181.md delete mode 100644 .changeset/shared-inbox-feed-4225.md delete mode 100644 .changeset/show-empty-related-plural-base-key-3863.md delete mode 100644 .changeset/sidebar-collapse-survives-reload-4234.md delete mode 100644 .changeset/six-bare-keys-defaults-4396.md delete mode 100644 .changeset/sort-relational-hint-stored-field-4294.md delete mode 100644 .changeset/spec-symbol-collisions-rc6-4167.md delete mode 100644 .changeset/sso-landing-setup-only-home-4048.md delete mode 100644 .changeset/studio-dock-polish-pins.md delete mode 100644 .changeset/studio-readonly-affordances-4036.md delete mode 100644 .changeset/synth-page-canonical-properties-4232.md delete mode 100644 .changeset/tall-eagles-repeat.md delete mode 100644 .changeset/tenant-locale-seeds-ui-language-4035.md delete mode 100644 .changeset/tidy-eels-invite.md delete mode 100644 .changeset/type-check-tests-auth-4040.md delete mode 100644 .changeset/type-check-tests-i18n-4040.md delete mode 100644 .changeset/type-check-tests-permissions-4040.md delete mode 100644 .changeset/type-check-tests-plugin-chatbot-4040.md delete mode 100644 .changeset/type-check-tests-plugin-form-4040.md delete mode 100644 .changeset/type-check-tests-plugin-gantt-4040.md delete mode 100644 .changeset/type-check-tests-plugin-map-4040.md delete mode 100644 .changeset/unpublished-banner-reads-unpublished-key-6955.md delete mode 100644 .changeset/updateview-draft-addressing-4139.md delete mode 100644 .changeset/useobjectchat-honest-message-type-4424.md delete mode 100644 .changeset/view-invalidation-seam-4373.md delete mode 100644 .changeset/view-overrides-invalidation-4363.md delete mode 100644 .changeset/widget-dom-leak-sweep-gate-4425.md delete mode 100644 .changeset/wild-pugs-smoke.md delete mode 100644 .changeset/wise-pumas-attack.md delete mode 100644 .changeset/wrong-slot-i18n-keys-4118.md diff --git a/.changeset/accept-invitation-single-route-3811.md b/.changeset/accept-invitation-single-route-3811.md deleted file mode 100644 index e4e0ce0313..0000000000 --- a/.changeset/accept-invitation-single-route-3811.md +++ /dev/null @@ -1,15 +0,0 @@ ---- -'@object-ui/console': minor -'@object-ui/i18n': minor -'@object-ui/app-shell': patch ---- - -`/accept-invitation/:invitationId` is one route, one component, one namespace — the console now renders the invitation page that actually shows you the invitation - -Two components shipped for this single URL. The console routed its own thin page, which offered nothing but an Accept and a Decline button: it never told the user which organization they had been invited to, in what role, or when the link expires, and accepting left them in whatever organization they were already in. App-shell's page — exported as `DefaultAcceptInvitationPage`, routed by nobody — fetches the invitation, shows the organization, the role and the expiry date, and switches the user into that organization on accept. Console now routes that one. The thin page is deleted. - -Behind them sat two i18n namespaces for one screen: `acceptInvitation.*` (12 keys) for the thin page and `organization.accept.*` (14) for the richer one, both freshly translated into ten languages by different slices of objectui#3546, neither wrong when read on its own. That is 26 keys of duplicated copy with no gate to tell the next author which of the two to edit — the failure mode this repo already has an uncollected precedent for. `acceptInvitation.*` is removed from all ten packs, and its absence is pinned negatively so it cannot drift back: the slice-three test now asserts that no pack defines any of the 12 retired keys (nor an emptied namespace root left by a partial revert), and that neither consuming package asks `t()` for one. - -One behavior needed repairing before the swap was safe rather than after. `?redirect=` is a basename-stripped path by contract in this console — `LoginPage` re-prefixes it with the mount before navigating — and the thin page built it from the route param, correctly. App-shell's page built it from `window.location.pathname`, which already carries the mount, so a console served under a `` would have sent the user back to `/console/console/accept-invitation/…` after signing in. It now reads the router (`useLocation`), like every other producer of that parameter in this repo. Under the default `/` mount the two spellings are identical, which is why only a basename case can see the difference; that case is now a test. - -Nothing published was removed: `DefaultAcceptInvitationPage` keeps its export and simply becomes the routed implementation. Downstream apps mounting it get the redirect fix and are otherwise untouched. diff --git a/.changeset/action-confirm-text-translation-4265.md b/.changeset/action-confirm-text-translation-4265.md deleted file mode 100644 index 73cbc80485..0000000000 --- a/.changeset/action-confirm-text-translation-4265.md +++ /dev/null @@ -1,25 +0,0 @@ ---- -'@object-ui/react': patch -'@object-ui/components': patch -'@object-ui/plugin-detail': patch -'@object-ui/app-shell': patch ---- - -Action confirm dialogs and success toasts now honour the bundle's translated -`confirmText` / `successMessage`, not just `label` (objectui#4265). - -A TranslationBundle entry for an action carries three keys under one -`_actions.` node — `label`, `confirmText`, `successMessage` — and -`useObjectLabel()` has always exposed a resolver for each. What had drifted was -the call sites: `page:header` (authored record pages), `record:quick_actions` -and the related-list row menu resolved the button `label` only and dispatched -the authored `confirmText` / `successMessage` untouched. One bundle entry met -two fates: the button rendered the translation, the confirm dialog rendered the -authored English. - -All action-rendering surfaces now go through one resolver, -`useActionTextLocalizer()` (new, exported from `@object-ui/react`), which -applies the existing `actionLabel` / `actionConfirm` / `actionSuccess` -resolvers over the three keys together. Fallback is unchanged: with no bundle -entry — or an entry lacking a key — the authored text renders. A bundle cannot -introduce a `confirmText` or `successMessage` the metadata never declared. diff --git a/.changeset/action-forward-whitelist-parity-4050-4192.md b/.changeset/action-forward-whitelist-parity-4050-4192.md deleted file mode 100644 index 111d9f9b2d..0000000000 --- a/.changeset/action-forward-whitelist-parity-4050-4192.md +++ /dev/null @@ -1,13 +0,0 @@ ---- -'@object-ui/components': patch ---- - -An action rendered in the overflow menu, as an icon or inside a group now reaches the runner carrying the same authored keys as the same action rendered inline — `action:menu`, `action:icon` and `action:group` forward `label` and `description`, and the two group/icon surfaces also forward `resultDialog`. - -Every action renderer hands the `ActionRunner` an explicit key WHITELIST rather than the action itself. That is deliberate — a key no renderer honours must not look wired — but the whitelists had drifted, and which renderer a given action gets is decided by `action:bar`'s `maxVisible` split (3 on desktop, 1 on mobile) and by `systemActions`, which are always in the overflow menu. So the same declared action behaved differently depending on the viewport. - -`label` and `description` are what the console's param-collection handler titles its dialog from (`title: action?.label || action?.title`, `description: actionDescription(…, action?.description)`). Dropped, an action with declared `params` opened a dialog titled "Action parameters" while the SAME declaration rendered inline named itself "Create Environment". `resultDialog` is the one-shot reveal spec (a fresh 2FA code, a newly minted OAuth secret): dropped, the runner falls back to the success toast and the value the user was meant to copy is gone — the objectui#3646 defect, still live on two of the four declared surfaces. - -`undoable` and `recordIdField` are deliberately NOT added. Both are read only under a `rowRecord` guard, and `rowRecord` is `params._rowRecord`, written exclusively by the spread-based hosts (`DeclaredActionsBar`, `RelatedRecordActionsBridge`, `ObjectGrid`, `page:header`), none of which dispatch through these renderers. They are unreachable on this path rather than dropped — `action:button` forwards them here inertly — so forwarding them would have added a second inert copy instead of restoring an affordance. - -A new repo gate, `pnpm check:action-forward-parity`, now derives each surface's owed key set (`authorable ∩ runtime-read − retired`) from the spec's own schemas and the consumers' ASTs and fails when a renderer drops one, so the seventh instance of this class fails on the pull request that introduces it rather than shipping green. diff --git a/.changeset/action-menu-autotrigger-overflow-4162.md b/.changeset/action-menu-autotrigger-overflow-4162.md deleted file mode 100644 index 44bbb23ac2..0000000000 --- a/.changeset/action-menu-autotrigger-overflow-4162.md +++ /dev/null @@ -1,13 +0,0 @@ ---- -'@object-ui/components': patch ---- - -An `autoTrigger` action that spills past `action:bar`'s `maxVisible` now still runs — `action:menu` consumes the flag instead of dropping it. - -`autoTrigger` is the client-composed "run this action as soon as a renderer receives it" flag behind deep links like the welcome page's "Create your environment" CTA (#844). It was consumed only by `action:button`. `action:bar` splits its post-gate list at `maxVisible` (3 on desktop, 1 on mobile) and hands the tail to `action:menu`, which had no `autoTrigger` handling at all — so an auto-triggered action that happened to sort past that threshold was rendered as an ordinary "More" menu entry and never ran, while the caller had already spent the one-shot signal it stood for. The `?runAction=create_environment` deep link is consumed by stripping it from the URL, so the measured end state was `urlParam=null execute=0`: no dialog, and no URL left to retry from. Which actions lost their auto-trigger was partly a function of viewport width, since `maxVisible` drops to 1 on mobile, and `systemActions` — always in the overflow menu, whatever the viewport — could never fire one at all. - -The flag's contract is now stated and enforced as "execute once on mount by whichever renderer receives the action". `action:menu` consumes it by EXECUTING, through the same path a click on that item takes; it does not open the dropdown, so a transport flag never moves what the user sees. Consumption happens where the action provably arrives — the menu renderer receiving it — not in the menu items, which Radix mounts only once the dropdown opens and which would therefore have waited on the very click the flag exists to avoid. - -Once-ness has one implementation (`renderers/action/auto-trigger.ts`), now shared by both renderers rather than written twice: a guard ref per rendered action, so re-renders never re-fire it and a flag that flips true later still fires exactly once. Container visibility still governs mounting — a hidden `action:bar` or `action:menu` renders no children and auto-triggers nothing — while the action's own `visible` gate does not suppress the trigger, matching `action:button`'s long-standing behaviour so that a deep link cannot depend on where the bar happened to put the action. - -The `action:bar` split, the inline `action:button` path and #4166's arming pins are unchanged. diff --git a/.changeset/action-typing-integrity-4418-4422.md b/.changeset/action-typing-integrity-4418-4422.md deleted file mode 100644 index 8499930692..0000000000 --- a/.changeset/action-typing-integrity-4418-4422.md +++ /dev/null @@ -1,18 +0,0 @@ ---- -'@object-ui/components': minor ---- - -The action renderers publish the modern `UIActionSchema`, and every `forwardRef` renderer's props parameter is annotated so its declared types survive - -**Breaking semantics (declared `minor` per the repo's version-alignment rule — objectui#4403 precedent — never `major`).** Six exported declarations in `@object-ui/components` change the action type they name, from the `@deprecated` legacy `ActionSchema` (`crud.ts`) to `UIActionSchema` (`ui-action.ts`): - -- `ActionBarSchema.actions`, `ActionBarSchema.systemActions` -- `ActionMenuSchema.actions` -- `ActionGroupSchema.actions` -- `ActionButtonProps.schema`, `ActionIconProps.schema` - -The two types are not interchangeable in either direction. `UIActionSchema` requires `name`, which legacy inherits as optional from `BaseSchema`; legacy pins `type: 'action'` where these renderers serve `'script' | 'url' | 'modal' | 'flow' | 'api'`; and only the modern type declares `locations`, `target`, `endpoint`, `bodyExtra`, `bodyShape` and a `variant` union containing `'primary'` — all of which the implementations already read. objectui#4417 measured four compiler errors proving the VALUES were modern while the DECLARATIONS said legacy; this moves the declarations to match, so the contract and the implementation finally agree. - -No runtime behaviour changes, and no published surface is involved: none of the six declarations is re-exported from the package index, and the sweep found zero type-checked consumers outside each declaration's own file. Metadata that renders today renders identically — the renderers read the same keys through the same paths. - -Separately, all fifteen `schema`-reading `forwardRef` renderers in the package now annotate their render function's first parameter directly, and carry the pass-through index signature on that annotation rather than on the `forwardRef` type argument. `forwardRef` routes its type argument through `PropsWithoutRef`, whose `Omit` collapses a props type carrying `[key: string]: any` down to the bare index signature — every declared property erased, silently, with `noImplicitAny` reporting clean because the `any` is supplied explicitly by the index signature. That is what hid the declaration/implementation drift above for as long as it lasted. Thirteen renderers recover a real declared type for `schema` (the two raw-tag factories keep `any`, which is what they genuinely declare), and a new structural guard, `forwardref-props-annotation.guard.test.ts`, fails on any future `forwardRef` that reintroduces either half of the trap. diff --git a/.changeset/actiondef-close-the-index-signature.md b/.changeset/actiondef-close-the-index-signature.md deleted file mode 100644 index 95ffedda4b..0000000000 --- a/.changeset/actiondef-close-the-index-signature.md +++ /dev/null @@ -1,51 +0,0 @@ ---- -"@object-ui/core": minor ---- - -Close `ActionDef` — delete the `[key: string]: any` index signature and converge `visible` / `disabled` on the spec's unified shape. - -`ActionDef` accepted any key of any type, so a typo (`targt`) and a retired spec -key (`execute`) both type-checked and the runner then silently bound no handler -— the objectstack#2169 "Mark Done does nothing" shape. Step 1 -(objectstack#4075) made that audible with a dev-mode warning; step 2 promoted -the 18 spec-owned keys to real fields. This is **step 3**, executing the -maintainer's 2026-08-06 ruling now that its upstream half shipped in -`@objectstack/spec` 17.0.0-rc.6 (objectstack#5970). - -- **`visible` and `disabled` now have ONE shape, derived from the spec** — - `boolean | string(CEL) | { dialect, source }`. The ruling was "统一形状,spec - 采纳": boolean is the degenerate literal verdict, the string is CEL shorthand, - the envelope is the full form. `visible` loses its hand-written `| boolean` - (the spec adopted that arm, so restating it locally would be a second - contract), and `disabled` gains the envelope arm it never had — it was - `string | boolean`, which is why the envelope the spec emits could only be - read through a cast. -- **The index signature is gone.** `tsc` now rejects an unknown or retired key - at any site that authors an action literal in code. -- **Five keys the deletion surfaced, promoted to real fields.** `to`, - `external`, `newTab`, `replace` — the `navigation` alias's own spelling, ruled - legitimate by step 1 and listed in `NAVIGATION_ALIAS_KEYS` ever since, but - declared only as data; and `description`, which every action renderer forwards - (`check:action-forward-parity` requires it) and the param-collection dialog - reads for its subtitle (objectui#4192). These were the only two `TS2353`s the - deletion produced across the whole workspace. -- **`ActionContext` keeps its index signature**, deliberately. It is a runtime - data bag whose keys are genuinely open; `ActionDef` is a declared metadata - contract. That asymmetry is the point, and it is now pinned in both - directions. - -**Breaking edge, deliberate — same class as step 2's, one step further.** An -`ActionDef` literal carrying a key this interface does not declare is now a -compile error where it previously compiled and did nothing at runtime. That -includes the retired `execute` (rename it to `target`; `os migrate meta --from -16` rewrites it) and plain typos. Values that were only ever absorbed silently -are the ones that stop compiling, so the failure moves to where it can be fixed -rather than appearing as a button that does nothing. - -**What did NOT retire with the index signature**, contrary to step 1's -expectation: the dev-mode `warnOnUnknownActionKeys` shim and `executeScript`'s -`execute` rename prescription both stay. `tsc` only ever sees actions authored -as TypeScript, while stored `sys_metadata` rows are rehydrated UNPARSED -(objectstack#3903) — which is the population `execute: 'markDone'` actually -lives in. The two mechanisms cover disjoint populations; retiring the runtime -half would have re-opened the gap it was written for. diff --git a/.changeset/address-display-formatter-4037.md b/.changeset/address-display-formatter-4037.md deleted file mode 100644 index f20b94c6a2..0000000000 --- a/.changeset/address-display-formatter-4037.md +++ /dev/null @@ -1,15 +0,0 @@ ---- -'@object-ui/fields': patch ---- - -A `Field.address` value now reads as a formatted postal address on the record detail page, instead of stringified JSON. - -The display (read) registry mapped `address` straight to `JsonCellRenderer`, so a populated address rendered as `{"street":"中策路 1 号","city":"杭州",…}` — while a `location` field sitting next to it in the same field group rendered formatted, and the create/edit dialog rendered the very same value as proper Street / City / State / ZIP / Country inputs. The gap was display-side only: the input registry has always carried `address`. Both read surfaces the detail page exposes are affected and both are fixed, because they share one `displayValue` path — read mode, and the inline-edit read state (the row carrying the pencil affordance, before a field is actually being edited). - -Layout is not invented for the read side. `AddressField`'s readonly branch already collapsed a stored address to a single line, and that rule — `Street, City, State ZIP, Country`, with `state` and the postal code sharing one comma group — is now the *only* implementation, moved into a pure `address-format` module that both surfaces call. A readonly form and a detail page therefore cannot spell one stored address two ways; a second copy next to the renderer would have been a rule that drifts. The module is deliberately React-free, so the eagerly-loaded barrel can format a cell without pulling `AddressField` and its inputs out of the lazy widget chunk. - -Partial values degrade the way the readonly line already did: absent, non-string and whitespace-only parts are dropped rather than spaced over, so a street-only address renders as `中策路 1 号` and never as `, , ,` or as the string `undefined`. Legacy records whose postal code was written under `zipCode` (objectstack#5143) still render it, matching what the input widget reads. - -Nothing is silently swallowed by the change: a value the formatter cannot recognize — an object carrying no known part — keeps today's compact-JSON rendering rather than disappearing, and `{}` or a null value shows the usual empty placeholder. A plain string address passes straight through. `location`, `geolocation`, and the genuinely structural `json` / `object` types are untouched. - -The address *input* is unchanged on every surface, including the create/edit dialog. diff --git a/.changeset/ai-build-thread-survives-preview-switch-2627.md b/.changeset/ai-build-thread-survives-preview-switch-2627.md deleted file mode 100644 index 87b5402d24..0000000000 --- a/.changeset/ai-build-thread-survives-preview-switch-2627.md +++ /dev/null @@ -1,15 +0,0 @@ ---- -'@object-ui/app-shell': patch ---- - -The AI build conversation no longer blanks itself the moment the preview opens - -`useChatConversation` treated every failed resolve the same way: clear the id, clear the messages. For a FIRST resolve that is right — there is nothing to lose. For a re-resolve of the conversation the hook is already holding it is destructive, and the AI build flow fires exactly such a re-resolve at the worst possible moment. - -The sequence is the magic-moment one. A build turn streams; `apply_blueprint`'s draft lands and the Live Canvas opens, switching the page from full-screen chat to the chat|preview split; the turn ends; ADR-0057 A1.b bind-on-create — which deliberately waits for that edge — re-keys the conversation to `app::build` and navigates to `?package=`. The scope flip re-resolves the same conversation, one GET issued at the instant the server is still finishing the heaviest turn of the session. A 502 or a dropped connection on that single request landed in the blanket catch. - -Clearing the id there is not a conservative fallback, because of what the host does with it: `AiChatPage` keys its chat pane on `` `${chatApi}:${conversationId ?? 'pending'}` ``, and the thread itself lives inside the chat hook's instance (`useObjectChat` seeds from `initialMessages` once per mount). So `undefined` does not re-render the pane, it REPLACES it, and the blueprint card, the build summary and the Publish button all leave with the discarded instance — the reported "the whole conversation went blank right after the build finished, and only came back after switching threads and back". - -A failed resolve now keeps whatever it was re-reading, when that is the conversation already held: the id is still valid and the messages are still the truth, so the surface stays as it was and the next resolve recovers. This is the other half of a guard that was already there for the empty case — the same re-resolve returning NO messages mid-turn was already refused the right to wipe hydrated history; only the failing case was still open. A resolve aimed at a DIFFERENT conversation (a sidebar switch) and a first resolve with nothing held still clear, and both are pinned negatively. - -Pinned at two levels: the hook, and the page driving the real build→preview→re-key sequence and asserting the pane is never remounted across it. diff --git a/.changeset/aichatpage-runtime-message-seam-4437.md b/.changeset/aichatpage-runtime-message-seam-4437.md deleted file mode 100644 index d53ee63a1b..0000000000 --- a/.changeset/aichatpage-runtime-message-seam-4437.md +++ /dev/null @@ -1,13 +0,0 @@ ---- -'@object-ui/app-shell': patch ---- - -`AiChatPage` narrows the chat hook's messages through the exported `toRuntimeMessages` adapter instead of five casts - -`useObjectChat` returns `ObjectChatMessage[]` — the shape both of its modes really produce (objectui#4424) — which is wide where local mode is wide: it keeps the authored `'tool'` role and the legacy `'partial-call'`/`'call'`/`'result'` tool states. This page wants the runtime shape, and said so five times with `messages as ChatMessage[]` (plus one `as unknown as` double cast). The narrowing was real and the casts were legal; what was missing is that a cast erases the whole difference rather than the intentional part of it, so nothing recorded which narrowing was meant and nothing could go red when it changed. - -There is now one conversion where the hook's values enter the page's runtime-typed world, memoized on `messages` exactly as the plugin's own three renderers do (objectui#4399). All five sites read it; no cast replaces them, and the `as unknown as` double cast at the bound-package derivation turned out to be unnecessary once the value is honestly typed. - -One behaviour changes, and it is the one the fold was measured for. `sanitizeChatMessagesForCache` declares its parameter's role as `'user' | 'assistant' | 'system'` — it has always asked for folded roles, and the cast is what let an unfolded `'tool'` past that declaration. Measured on a thread carrying one: the entry was cached as `role: 'tool'`, which the cache's own reader then rejects, so the message vanished on a cache-fallback reload; and because sanitize gates tool serialization on `role === 'assistant'`, that turn's tool invocations — including the re-serialized draft envelope behind "Review N changes / Publish" — never reached the cache at all. Folded, both survive the reload they exist to survive. The other two compute sites were measured to be fold-insensitive and are unchanged: `isConversationZh` reads `role === 'user'` and the text, which the fold can neither create nor destroy, and `deriveBoundPackageId` walks every message irrespective of role and reads keys the adapter spreads through. - -Nothing on screen moves today: neither a `'tool'` role nor a legacy tool state is producible on this page's own paths, since hydration yields runtime roles and API mode's values come from `mapMessages` with v6 states already. This closes the hole ahead of a value that can reach it, and makes a future vocabulary move surface as a type error at the host rather than as rendering behaviour. diff --git a/.changeset/analytics-label-net-shared-glue-4389.md b/.changeset/analytics-label-net-shared-glue-4389.md deleted file mode 100644 index 9e6bf8a0d2..0000000000 --- a/.changeset/analytics-label-net-shared-glue-4389.md +++ /dev/null @@ -1,16 +0,0 @@ ---- -'@object-ui/core': patch -'@object-ui/react': patch -'@object-ui/plugin-dashboard': patch -'@object-ui/plugin-report': patch ---- - -Analytics: the dimension label net's fetch-and-memo glue is written once, not once per surface - -PR #4388 (objectui#4330) put the same React glue on two surfaces — the dashboard's `DatasetWidget` and plugin-report's dataset block. The resolution RULES were never duplicated (both call the same `@object-ui/core` helpers), but the wiring around them was: read the object schema through the host's authenticated `apiFetch`, keep the fetched metadata locale-free in state, derive the label maps in a render memo. Two copies meant two statements of the same two bug fixes, which is a drift surface rather than a defect — nothing a user could hit today, filed as objectui#4389 so it was retired deliberately. - -It is now split along the layer that can actually hold each half. `@object-ui/core` gains the React-free parts — `loadDimensionFieldMeta` (the base-object read composed with the dimension walk), `deriveDimensionLabelMaps` (the locale-applying derivation) and `dimensionOptionTranslator` (binding the bundle resolver to the object that OWNS a terminal field, which for a dotted path is the relationship target). `@object-ui/react` gains `useDatasetDimensionLabels` / `useDatasetDimensionMeta`, the React wiring that cannot live in core, beside the `useViewData` / `useElementDataSource` / `useDiscovery` hooks that already read `SchemaRendererContext` the same way. Both plugins consume it; the dashboard keeps its chart-only per-category colour and category-order derivation layered locally, since a table renders no palette. - -The card originally proposed `@object-ui/core` as the whole glue's home. That home was disproven by measurement and retired in the card's PM RULING #2: `SchemaRendererContext` is defined in `@object-ui/react`, which depends on core, so core importing it back is a cycle — and core is React-free by declaration, by content, and by the topology in AGENTS.md. objectui#3367 had already ruled this direction for the same family (core-canonical logic, react re-exports). - -Behaviour is unchanged by construction: same read count, same best-effort fallback, same memoization boundary. The two bug fixes are now stated once and pinned at the shared hook — the read rides the host's authenticated `apiFetch` (objectui#4121, pinned by asserting that a new channel re-issues the read, i.e. that it really is in the effect's deps), and the fetched metadata stays locale-free (objectui#4030 / PR #4324, pinned by switching language at runtime and asserting the labels flip with no second metadata read). All 39 assertions PR #4388 landed across both surfaces pass unchanged, and their files are byte-identical to before. diff --git a/.changeset/analytics-option-label-i18n-4030.md b/.changeset/analytics-option-label-i18n-4030.md deleted file mode 100644 index 65206812ad..0000000000 --- a/.changeset/analytics-option-label-i18n-4030.md +++ /dev/null @@ -1,17 +0,0 @@ ---- -'@object-ui/core': patch -'@object-ui/plugin-dashboard': patch -'@object-ui/plugin-charts': patch ---- - -Analytics surfaces now run resolved select-option labels through the locale bundle — the chart legend and the related list on one page stop disagreeing - -A dashboard widget grouped by a `select` field rendered the option's authored English label while the related list beside it rendered the translation. The decisive evidence in objectui#4030 is the stored value `orion`: the chart read `Orion Engineered Carbons`, a string with no resemblance to the value and matching the object's `label` byte for byte. So the analytics path had already RESOLVED the option label — it simply never ran the result through the i18n bundle before display. (`domestic → Domestic` differs from its value by case alone, which is why the first diagnosis, "the report groups by stored value", was wrong.) - -There is exactly one resolution channel and this change reuses it rather than adding a chart-side dialect: `fieldOptionLabel` from `useObjectLabel`, i.e. `{ns}.fieldOptions...` — the convention `@objectstack/spec` names objectui as the reader of, and the one list, form, kanban and record-picker surfaces already translate select options through. The bundle is applied ONCE, at the output of the label net that landed in objectui#4053/#4263, on the shared option list every consumer reads: chart axis and legend, the table/pivot cells of a dotted dimension, that table's CSV export, per-category colours and the declared category order. `@object-ui/core` gains `localizeFieldOptions` (the pure mirror of `translateOptions`), an optional translator on `buildDimensionLabelMap`, and `resolveDimensionFieldMeta` — the same single relationship walk `resolveDimensionFieldOptions` performs, now keeping the object that OWNS the terminal field, because for `crm_account.industry` the bundle key is `crm_account`, not the dataset's base object. - -Two properties the fix is shaped around. The rows reach this net keyed either way — by stored value when the server did not resolve the dimension, by the English label when it did (ADR-0021) — and the reported screen is the second case, so the map answers to both keys and lands on the same translated display. And identity is untouched: `relabelDimensions` still rewrites display only, so a drilled chart segment clicked as `欧励隆` filters by `orion`, bucket ids and pivot totals keep their raw keys, and an option with no bundle entry (or an `en` console) renders exactly the authored label it renders today. - -The per-locale work moved from the metadata fetch into the render, so switching language now re-labels in place instead of waiting for a refetch. - -Not covered, and unchanged here: a LOCAL select dimension on a table/pivot, whose label the server resolves and whose client-side net is deliberately off (objectui#4263), and a dashboard global filter's own field label, which has no object name in its metadata to key a bundle lookup with — tracked on objectui#4030. diff --git a/.changeset/api-console-storage-slot-key-4240.md b/.changeset/api-console-storage-slot-key-4240.md deleted file mode 100644 index 398a06306b..0000000000 --- a/.changeset/api-console-storage-slot-key-4240.md +++ /dev/null @@ -1,11 +0,0 @@ ---- -'@object-ui/console': patch ---- - -API Console renders the Storage group again — its catalog key now names the canonical `file-storage` slot instead of the route - -The API Console's service-gated groups are keyed by canonical service-slot name, because the key is looked up directly in `/discovery`'s `services` map — and the framework keys that map by `CoreServiceName`. The storage group was keyed `storage`, which is the *route* (`/api/v1/storage`), not the slot (`file-storage`). So the lookup missed on every host, and because a miss is indistinguishable from "no such service" the deliberate fail-closed branch (ADR-0076 D12) hid all three storage endpoints — upload, download, delete — on every deployment, whether or not a storage service was registered and healthy. - -The fail-closed posture was never the defect and is unchanged; only the key moves. The group's user-facing name stays `Storage` — that is the route's name, and it was never derived from the catalog key, so no display string and no i18n resource changes. - -The mis-key survived because nothing tied the catalog's keys to the vocabulary they are spelled in: a wrong key produces silence, not an error, and an empty group is exactly what a legitimately absent service looks like. A tripwire now derives that vocabulary from `@objectstack/spec` itself and asserts every service-gated catalog key against it, so a rename on either side fails a test instead of quietly emptying a group. Deriving it also surfaced two further keys that name no slot and therefore can never render — `workflow` (slot retired upstream) and `feed` (never a slot) — recorded as a documented exception set pointing at objectui#4303 rather than fixed here, since neither has a correctly-spelled name to move to. diff --git a/.changeset/app-management-page-i18n-4307.md b/.changeset/app-management-page-i18n-4307.md deleted file mode 100644 index 78f5bfadb1..0000000000 --- a/.changeset/app-management-page-i18n-4307.md +++ /dev/null @@ -1,35 +0,0 @@ ---- -'@object-ui/i18n': patch -'@object-ui/console': patch ---- - -The console's Applications page is localized — its own chrome only, never the -server's words (objectui#4307). - -`AppManagementPage` was raw English end to end: headings, the search field, the -selection and bulk controls, the six per-row actions with their tooltip/ARIA -pairs, the status badges, and every toast. It was the last un-i18n'd system page, -and #4233 / PR #4300 had just given it four live mutations — so the gap became -user-visible on every non-English console at the moment operators started using -it. 45 keys land under `appManagement.*` in all ten packs, reached through -`useObjectTranslation` with the call site's `defaultValue` inline, which is the -convention the neighbouring system pages already follow. - -The split that shapes this change is between the strings the PAGE authors and -the strings the SERVER authors. `PUT`/`DELETE /api/v1/meta/app/:name` is gated on -`manage_metadata` (ADR-0066 D1), so a refusal like `forbidden: manage_metadata -required` is the server's diagnosis of one specific request; there is no fixed -catalogue of those sentences to key against. Each failure toast is therefore a -keyed template with a `{{reason}}` hole, and what fills the hole is passed -through byte for byte, untranslated. The one part that IS the page's own — what -it says when the server sent no message at all — is keyed as -`appManagement.toast.unknownError`. - -Two smaller things follow from doing the conversion properly rather than -mechanically. The per-failure entry of a bulk toast and the separator between -entries are keys, not literals, because bracket style and list punctuation are -locale properties (the same rule, and the same past defect, as -`validation.formInvalidJoiner`). And the row's controls now name an app through -the resolver the visible heading two lines away already used, with `t` passed: -an app carrying objectui's keyed label form previously rendered `Select [object -Object]` into its checkbox's ARIA label. diff --git a/.changeset/app-management-search-keyed-label-4343.md b/.changeset/app-management-search-keyed-label-4343.md deleted file mode 100644 index 62acaa3625..0000000000 --- a/.changeset/app-management-search-keyed-label-4343.md +++ /dev/null @@ -1,19 +0,0 @@ ---- -'@object-ui/console': patch ---- - -The Applications page's search box no longer takes the page out on the first keystroke when an app carries a non-string label - -`apps/console/src/pages/system/AppManagementPage.tsx` filtered on `(app.label || '').toLowerCase()`. `label` and `description` are `I18nLabel` in `AppSchema` — `string | Record< string, string >` in `@objectstack/spec` 17.0.0-rc.6 — so an authored non-string label is spec-legal metadata, and an object is **truthy**: the `|| ''` guard never fired for one, and `.toLowerCase()` received the object. - -``` -TypeError: (l || "").toLowerCase is not a function -``` - -That throw happened inside `filter` **during render**, so it took the whole page down rather than degrading search. It stayed invisible until someone typed, because `if (!searchQuery) return true` returns before either read — the page mounted perfectly with the very metadata that killed it one character later. - -Both reads now go through the resolver the rows already render with: `appTitle` (the single display-name helper objectui#4307 introduced in this file) for the label, and the identical `resolveKeyedI18nLabel(…, t)` call the description paragraph makes. This is a repair to one page's filter, not a new capability — but it does make search match what the operator can actually see: for objectui's keyed label form it now matches the pack's answer rather than the authoring `defaultValue`, and it matches `app.name` wherever the row heading itself falls back to it. - -Routing search through the render path also means it cannot drift out of step again. The inline locale map form (`{ en: 'Storefront', 'zh-CN': '店面' }`) is still resolved by neither path — the row heading falls back to the app name and search now matches on exactly that, instead of crashing on it — so when objectui#4163 widens the resolver, display and search gain the map form in the same commit. - -No first-party app ships a non-string app label today, so this was reachable through authored metadata rather than live in the shipped examples; the crash is real for anyone who authored one, and `AppSchema` accepts it with a green parse. diff --git a/.changeset/autonumber-textual-ref-fallback-4219.md b/.changeset/autonumber-textual-ref-fallback-4219.md deleted file mode 100644 index 147917e610..0000000000 --- a/.changeset/autonumber-textual-ref-fallback-4219.md +++ /dev/null @@ -1,13 +0,0 @@ ---- -'@object-ui/plugin-detail': patch ---- - -Inline edit no longer offers a record picker for a spec-spelled `autonumber` field that carries a `reference_to` - -`TEXTUAL_REF_FALLBACK_TYPES` — the detail page's one definition of "machine-computed" — spelled the auto-number type `auto_number` only. `@objectstack/spec`, the designer and the metadata importer all spell it `autonumber`, and the set is matched by RAW spelling, so it carried half the type. - -The reader that had no gate in front of it is `InlineFieldInput`'s reference fallback, `!!field.reference_to && !TEXTUAL_REF_FALLBACK_TYPES.has(type)`, on exported public API. A field typed `autonumber` keeps a `reference_to` for relational metadata — which is the entire reason this set exists — so it took the lookup branch and rendered the RECORD PICKER: a searchable list of records offered as replacements for a machine-generated identity. The `auto_number` spelling of the identical field rendered the textual fallback, as intended. Both spellings are now members, matching how `plugin-form` carries both in each of its non-input sets. - -The editability half of the same report (objectui#4219) was already closed from another direction by #4228, whose shared exclusion resolves aliases before matching — a field typed `autonumber` offers no inline affordance in either host. The two gates are a union, so this fix also removes the union's dependence on which spelling the metadata happens to use: previously `autonumber` was held by the exclusion gate alone and `auto_number` by both, and losing either gate would have re-opened a different half of the defect depending on how the field was authored. - -Pins land with it: the reference fallback for `autonumber` (red before this change — the picker really did render), `auto_number` and a real `lookup` as controls in both directions, and set membership asserted directly so the union statement is checked rather than described. diff --git a/.changeset/bell-approvals-activity-off-app-4197.md b/.changeset/bell-approvals-activity-off-app-4197.md deleted file mode 100644 index 8f140601d4..0000000000 --- a/.changeset/bell-approvals-activity-off-app-4197.md +++ /dev/null @@ -1,13 +0,0 @@ ---- -'@object-ui/app-shell': patch ---- - -The bell's Approvals and Activity tabs fill in on Home, Organizations and the AI screen — from the same fetch the cards below them already use - -The top bar's bell renders on every console surface, but two of the three streams that fill it were gated on `variant === 'app'`: the pending-approvals poll and the `sys_activity` read. Off-app the popover therefore held nothing to show — the Approvals tab read "No pending approvals" and the Activity tab "No recent activity" — on the very page whose own To-do and activity cards were listing both, from the same endpoint and the same object. Neither stream is app-scoped: approvals are scoped to the signed-in user, activity to the tenant. Whichever app happened to be in the URL was never part of either query. - -The badge made the inconsistency arithmetic. It is `unreadTopics + pendingApprovalsCount`, and after objectui#4199 un-gated the inbox half, only the first addend was fetched outside an app — so one user with one set of data read 1 on Home and 3 inside an app, and the popover's own breakdown line disagreed with the number on the bell. - -Un-gating alone would have fixed the emptiness by paying for it twice: on `/home` the bell and the cards mount in one tree, so each owning its own effect means the approvals request and the `sys_activity` read both go out twice per page. They now share one fetch. A module-scoped store (`hooks/sharedUserFeeds`) owns each feed — one in-flight request, one 30s approvals poll, one 404-retires-the-feature rule — and both the bell and `useHomeInbox` subscribe to it. The dedupe is structural rather than agreed: there is no longer a second producer that could drift, so the badge and the card cannot show different numbers. Home's card keeps its narrower cut of the rows (human actors only, `sys_*`/`ai_*` churn dropped) by filtering the shared feed at its own call site rather than by issuing its own query. - -`isApp` keeps the meaning it was introduced for. The presence avatars and the connection dot are app-shell chrome and stay behind it — and presence was never a read to begin with: it is a transport-level subscription (`useTenantPresence`), which is why the effect that used to be called `fetchPresenceAndActivities` only ever fetched `sys_activity`. The boundary this draws is data scope, not surface: user- and tenant-scoped feeds follow the bell everywhere it renders, app-scoped chrome does not. diff --git a/.changeset/bell-panel-render-oracle-4230.md b/.changeset/bell-panel-render-oracle-4230.md deleted file mode 100644 index 88a3011743..0000000000 --- a/.changeset/bell-panel-render-oracle-4230.md +++ /dev/null @@ -1,20 +0,0 @@ ---- ---- - -Internal only — tests and comments, no source change, so no release. - -#4230 reported the console bell panel dead again ("No notifications" under both -Unread and All while `/api/v1/notifications` returned 10 rows) and filed it as a -regression of #4110 / PR #4199. It is not a regression: the QA build vendored -console `09987b68` (2026-08-09 02:35:56Z) and #4199 landed as `7b0783232` -(2026-08-10 20:39:10Z), 42 hours later — `git merge-base --is-ancestor 7b0783232 -09987b68` exits non-zero, and that console's `AppHeader.tsx` still carries the -`isApp` gate #4199 removed. No production code needed changing. - -What the round did expose is a hole in #4199's own pin: every case in -`AppHeader.inboxVariant.test.tsx` held one row and never touched the popover's -Unread/All sub-filter, so nothing could distinguish "Unread is empty because -every row is read" from "the panel was handed nothing" — and the second reading -under All is the load-bearing half of the reported symptom. This adds eight -cases driving the QA payload (ten rows, mixed read-state, including the -`approval.reminder`) through `AppHeader` and `InboxPopover` under both filters. diff --git a/.changeset/bridge-density-prototype-guard-4442.md b/.changeset/bridge-density-prototype-guard-4442.md deleted file mode 100644 index ca6060e99b..0000000000 --- a/.changeset/bridge-density-prototype-guard-4442.md +++ /dev/null @@ -1,24 +0,0 @@ ---- -'@object-ui/react': patch ---- - -The spec bridge abstains on prototype-member `rowHeight` spellings instead of leaking a -function into `density`. - -`bridgeListView`'s `mapDensity` indexed a plain object literal with an unchecked key, so -the lookup reached `Object.prototype`. The parameter is typed `RowHeight`, but the -boundary a host's stored view definition actually crosses is `SpecBridge.transformListView`, -whose parameter is `any` — so `rowHeight: 'toString'` came back as `Object.prototype.toString`, -a **function**, out of a read whose return type is three strings or nothing. `bridgeListView` -then writes the key under `if (density)`, and a function is truthy, so the bad value was not -merely returned: it was stored on a `SchemaNode` whose renderer expects -`'compact' | 'comfortable' | 'spacious'`. Same for `constructor`, `valueOf`, -`hasOwnProperty`, `isPrototypeOf`, `propertyIsEnumerable` and `toLocaleString`. - -The lookup is now guarded with `Object.prototype.hasOwnProperty.call(...)` — the same guard -`@object-ui/core`'s `rowHeightToDensityMode` grew in objectui#4440, and the repo's existing -convention at eight other sites. Both `rowHeight` surfaces now abstain identically on every -off-spec **string** spelling, and objectui#4440's agreement pin covers the prototype-member -family instead of excluding it (objectui#4442). - -Runtime-only: no public type moved, and no spec-valid `rowHeight` changes its answer. diff --git a/.changeset/button-has-type-lint-4045.md b/.changeset/button-has-type-lint-4045.md deleted file mode 100644 index caa69eab2b..0000000000 --- a/.changeset/button-has-type-lint-4045.md +++ /dev/null @@ -1,23 +0,0 @@ ---- -'@object-ui/app-shell': patch -'@object-ui/components': patch -'@object-ui/console': patch -'@object-ui/plugin-ai': patch -'@object-ui/plugin-designer': patch -'@object-ui/plugin-kanban': patch -'@object-ui/plugin-map': patch -'@object-ui/plugin-view': patch -'@object-ui/react': patch -'@object-ui/runner': patch ---- - -Every plain `