fix(app-shell): the field-rule wrong-layer verdict comes from @objectstack/lint, not a second copy of it - #9366
fix(app-shell): the field-rule wrong-layer verdict comes from @objectstack/lint, not a second copy of it#9366os-tesla wants to merge 2 commits into
Conversation
…stack/lint, not a second copy of it `rowCanonAdvisory` answered "is this root bound on this surface?" from objectui's own knowledge: `@object-ui/core`'s `detectNonCanonicalRowSpelling` hard-codes the single root `data`, and the docblock justified that from `ROW_PREDICATE_ROOTS` / `FIELD_RULE_ROOTS` / `FORMULA_ROOTS`. The platform publishes the same judgement as `fieldRuleRootIssue` / `FIELD_RULE_BOUND_ROOTS`. They agree today and nothing keeps them agreeing. `CelSchemaHint.slot` names the authored key, and on the slots the published vocabulary covers — visibleWhen / readonlyWhen / requiredWhen — the verdict and the message are now the helper's. Both symbols are module-internal to app-shell; no package export moves. Coverage is not shrunk to fit the helper: a formula `expression` binds `FORMULA_ROOTS` (narrower) and a conditional-formatting `condition` binds `ROW_PREDICATE_ROOTS` (wider), so both keep the local instrument, pinned as live controls. Part of #9318 Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UzHd6hDYatoDn17BuwKxnZ
|
| Step | Outcome |
|---|---|
| Build packages | success |
| Check console performance budget | failure |
Which half objected:
| Eager-closure half | Verdict |
|---|---|
| Aggregate closure ceiling | ✅ pass |
| Per-chunk ceilings | ✅ pass |
| Ceiling sensitivity (headroom) | |
| Ceiling freshness (checkout vs. base branch) | ✅ pass |
⚠️ A broken gauge half is a verdict about the ceiling, not about the bundle: that line has drifted out of range of the regression it exists to catch, or the report behind it cannot be trusted. It does not say anything grew. TheCheck console performance budgetstep log carries the ceiling and the number it was compared against.
Reason: The entry chunk measured 144.3 KB, but the eager-closure half of this gate returned no trustworthy VERDICT: the report could not be read, a ceiling has drifted out of range of the regression it must catch, or (objectui#6245) a ceiling was replaced on the base branch after this checkout was made. The step log says which. This is not a passing budget — and it is not a size regression either.
See the workflow run for details.
📦 Bundle Size Report
| Package | Size | Gzipped |
|---|---|---|
| app-shell (consoleActionDispatch.js) | 0.20KB | 0.19KB |
| app-shell (index.js) | 16.69KB | 6.21KB |
| app-shell (runtime-config.js) | 20.68KB | 7.36KB |
| app-shell (types.js) | 0.01KB | 0.04KB |
| app-shell (urlParams.js) | 10.06KB | 3.86KB |
| auth (ActiveOrganizationStorage.js) | 25.05KB | 9.16KB |
| auth (AuthContext.js) | 0.31KB | 0.24KB |
| auth (AuthGuard.js) | 2.07KB | 1.00KB |
| auth (AuthProvider.js) | 40.18KB | 10.59KB |
| auth (AuthShell.js) | 3.49KB | 1.40KB |
| auth (ForgotPasswordForm.js) | 12.21KB | 3.45KB |
| auth (LoginForm.js) | 18.15KB | 5.39KB |
| auth (PreviewBanner.js) | 0.90KB | 0.50KB |
| auth (RegisterForm.js) | 6.65KB | 2.22KB |
| auth (SocialSignInButtons.js) | 9.61KB | 3.89KB |
| auth (UserMenu.js) | 3.41KB | 1.23KB |
| auth (auth-gate-events.js) | 1.29KB | 0.66KB |
| auth (authStyles.js) | 5.04KB | 1.72KB |
| auth (createAuthClient.js) | 40.21KB | 10.80KB |
| auth (createAuthenticatedFetch.js) | 8.46KB | 3.43KB |
| auth (index.js) | 3.19KB | 1.44KB |
| auth (invitation-status.js) | 1.22KB | 0.70KB |
| auth (org-roles.js) | 6.66KB | 2.78KB |
| auth (phone-identifier.js) | 1.11KB | 0.66KB |
| auth (types.js) | 0.59KB | 0.35KB |
| auth (useAuth.js) | 5.30KB | 1.02KB |
| auth (useWorkspaceAdminStatus.js) | 11.08KB | 4.58KB |
| collaboration (CommentThread.js) | 26.08KB | 7.56KB |
| collaboration (LiveCursors.js) | 3.17KB | 1.27KB |
| collaboration (PresenceAvatars.js) | 6.49KB | 2.64KB |
| collaboration (PresenceProvider.js) | 2.79KB | 1.13KB |
| collaboration (index.js) | 1.68KB | 0.73KB |
| collaboration (useCollaborationTranslation.js) | 6.05KB | 2.52KB |
| collaboration (useCommentSearch.js) | 1.98KB | 0.88KB |
| collaboration (useConflictResolution.js) | 7.75KB | 1.86KB |
| collaboration (useMentionNotifications.js) | 1.81KB | 0.68KB |
| collaboration (usePresence.js) | 6.33KB | 1.84KB |
| collaboration (useRealtimeSubscription.js) | 7.91KB | 2.01KB |
| components (index.js) | 502.02KB | 115.16KB |
| core (index.js) | 8.52KB | 3.41KB |
| create-plugin (index.js) | 27.94KB | 9.51KB |
| data-objectstack (index.js) | 211.58KB | 58.68KB |
| fields (index.js) | 247.89KB | 62.50KB |
| i18n (LocalizationContext.js) | 1.76KB | 0.96KB |
| i18n (builtinAggregateLabels.js) | 0.86KB | 0.49KB |
| i18n (currency.js) | 1.22KB | 0.64KB |
| i18n (fallbackInterpolation.js) | 6.25KB | 2.77KB |
| i18n (i18n.js) | 8.87KB | 3.64KB |
| i18n (index.js) | 5.22KB | 2.26KB |
| i18n (pickLocalized.js) | 9.86KB | 3.95KB |
| i18n (provider.js) | 32.15KB | 10.49KB |
| i18n (useDisplayLocale.js) | 2.85KB | 1.45KB |
| i18n (useObjectLabel.js) | 34.34KB | 9.17KB |
| i18n (useSafeTranslation.js) | 5.60KB | 2.33KB |
| layout (index.js) | 38.83KB | 10.95KB |
| mobile (MobileProvider.js) | 0.92KB | 0.49KB |
| mobile (ResponsiveContainer.js) | 0.94KB | 0.38KB |
| mobile (breakpoints.js) | 1.51KB | 0.70KB |
| mobile (createOfflineDataSource.js) | 5.61KB | 1.75KB |
| mobile (index.js) | 1.99KB | 0.87KB |
| mobile (offlineQueue.js) | 3.91KB | 1.35KB |
| mobile (pwa.js) | 0.97KB | 0.49KB |
| mobile (serviceWorker.js) | 1.48KB | 0.62KB |
| mobile (serviceWorkerSource.js) | 3.41KB | 1.48KB |
| mobile (useBreakpoint.js) | 1.54KB | 0.65KB |
| mobile (useGesture.js) | 6.96KB | 1.98KB |
| mobile (useOfflineSync.js) | 1.99KB | 0.72KB |
| mobile (usePullToRefresh.js) | 2.53KB | 0.85KB |
| mobile (useResponsive.js) | 0.72KB | 0.42KB |
| mobile (useSpecGesture.js) | 4.39KB | 1.66KB |
| mobile (useTouchTarget.js) | 1.01KB | 0.54KB |
| permissions (MePermissionsProvider.js) | 13.52KB | 4.88KB |
| permissions (PermissionContext.js) | 0.31KB | 0.25KB |
| permissions (PermissionGuard.js) | 0.89KB | 0.45KB |
| permissions (PermissionProvider.js) | 6.24KB | 2.16KB |
| permissions (discardProofCache.js) | 1.04KB | 0.55KB |
| permissions (evaluator.js) | 8.39KB | 3.10KB |
| permissions (index.js) | 0.93KB | 0.41KB |
| permissions (store.js) | 0.91KB | 0.42KB |
| permissions (useFieldPermissions.js) | 1.28KB | 0.53KB |
| permissions (usePermissions.js) | 4.83KB | 2.27KB |
| plugin-ai (index.js) | 14.81KB | 3.63KB |
| plugin-calendar (index.js) | 49.25KB | 13.99KB |
| plugin-charts (index.js) | 71.51KB | 19.97KB |
| plugin-chatbot (index.js) | 195.34KB | 46.51KB |
| plugin-dashboard (index.js) | 131.22KB | 34.59KB |
| plugin-designer (index.js) | 215.94KB | 44.33KB |
| plugin-detail (index.js) | 253.46KB | 65.85KB |
| plugin-editor (index.js) | 2.23KB | 1.05KB |
| plugin-form (index.js) | 136.77KB | 34.17KB |
| plugin-gantt (index.js) | 166.95KB | 41.04KB |
| plugin-grid (index.js) | 211.58KB | 57.48KB |
| plugin-kanban (index.js) | 46.01KB | 14.30KB |
| plugin-list (index.js) | 112.58KB | 27.65KB |
| plugin-map (index.js) | 20.64KB | 6.86KB |
| plugin-markdown (index.js) | 13.88KB | 4.80KB |
| plugin-report (index.js) | 43.41KB | 11.93KB |
| plugin-timeline (index.js) | 30.07KB | 8.74KB |
| plugin-tree (index.js) | 9.55KB | 3.32KB |
| plugin-view (index.js) | 84.42KB | 20.79KB |
| providers (DataSourceProvider.js) | 0.75KB | 0.39KB |
| providers (MetadataProvider.js) | 1.37KB | 0.59KB |
| providers (ThemeProvider.js) | 1.90KB | 0.85KB |
| providers (UploadProvider.js) | 11.66KB | 3.50KB |
| providers (index.js) | 0.45KB | 0.23KB |
| providers (types.js) | 0.01KB | 0.04KB |
| react-runtime (index.js) | 5.62KB | 2.34KB |
| react (LazyPluginLoader.js) | 4.47KB | 1.63KB |
| react (SchemaRenderer.js) | 94.03KB | 31.02KB |
| react (data-invalidation.js) | 5.05KB | 2.08KB |
| react (index.js) | 4.63KB | 2.18KB |
| react (schema-input.js) | 4.25KB | 2.04KB |
| react (spec-input.js) | 0.20KB | 0.18KB |
| sdui-parser (codegen.js) | 6.58KB | 2.74KB |
| sdui-parser (dashboard-widget-options.js) | 3.08KB | 1.30KB |
| sdui-parser (index.js) | 5.66KB | 2.50KB |
| sdui-parser (input-type.js) | 2.84KB | 1.40KB |
| sdui-parser (kanban-quick-add.js) | 3.89KB | 1.87KB |
| sdui-parser (parse.js) | 25.28KB | 7.80KB |
| sdui-parser (provenance.js) | 3.66KB | 1.82KB |
| sdui-parser (types.js) | 0.28KB | 0.23KB |
| sdui-parser (validate.js) | 14.82KB | 4.99KB |
| types (ai.js) | 0.20KB | 0.17KB |
| types (api-types.js) | 0.20KB | 0.18KB |
| types (app.js) | 2.87KB | 1.00KB |
| types (base.js) | 0.20KB | 0.18KB |
| types (blocks.js) | 0.20KB | 0.18KB |
| types (complex.js) | 2.93KB | 1.49KB |
| types (crud.js) | 0.20KB | 0.18KB |
| types (dashboard-filter-alias.js) | 6.23KB | 2.74KB |
| types (data-display.js) | 3.75KB | 1.85KB |
| types (data-protocol.js) | 0.20KB | 0.19KB |
| types (data.js) | 0.20KB | 0.18KB |
| types (designer.js) | 1.85KB | 0.85KB |
| types (disclosure.js) | 0.20KB | 0.18KB |
| types (error-code.js) | 1.54KB | 0.88KB |
| types (expression.js) | 0.20KB | 0.18KB |
| types (feedback.js) | 0.20KB | 0.18KB |
| types (field-types.js) | 0.20KB | 0.18KB |
| types (form.js) | 0.20KB | 0.18KB |
| types (http-inflight.js) | 8.87KB | 3.73KB |
| types (http-retry.js) | 4.32KB | 2.02KB |
| types (icon-key-migration.js) | 4.26KB | 1.63KB |
| types (index.js) | 4.74KB | 2.25KB |
| types (layout.js) | 0.20KB | 0.18KB |
| types (managed-by.js) | 0.19KB | 0.18KB |
| types (mobile.js) | 4.73KB | 2.28KB |
| types (navigation.js) | 0.20KB | 0.18KB |
| types (objectql.js) | 0.20KB | 0.18KB |
| types (overlay.js) | 0.20KB | 0.18KB |
| types (permissions.js) | 0.20KB | 0.18KB |
| types (plugin-scope.js) | 0.20KB | 0.18KB |
| types (record-components.js) | 0.20KB | 0.19KB |
| types (record-semantics.js) | 1.28KB | 0.67KB |
| types (registry.js) | 0.20KB | 0.18KB |
| types (reports.js) | 0.20KB | 0.18KB |
| types (select-option.js) | 0.20KB | 0.19KB |
| types (spec-report.js) | 5.05KB | 1.93KB |
| types (spec-ui-namespace.js) | 0.20KB | 0.19KB |
| types (strict-authoring-face.js) | 14.27KB | 5.47KB |
| types (system-fields.js) | 3.33KB | 1.54KB |
| types (theme.js) | 6.28KB | 2.87KB |
| types (ui-action.js) | 8.11KB | 3.32KB |
| types (views.js) | 0.20KB | 0.18KB |
| types (widget.js) | 0.20KB | 0.18KB |
Size Limits
- ✅ Core packages should be < 50KB gzipped
- ✅ Component packages should be < 100KB gzipped
⚠️ Plugin packages should be < 150KB gzipped
…-from-lint Base-only sync: brings the branch onto a main that contains 8524372 (feat(react)!: unbind the data-source adapter from the expression scope). No file owned by this pull request is modified by this commit. Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01L5xpA5q533BgTTNADibEFt
|
| Step | Outcome |
|---|---|
| Build packages | success |
| Check console performance budget | failure |
Which half objected:
| Eager-closure half | Verdict |
|---|---|
| Aggregate closure ceiling | ✅ pass |
| Per-chunk ceilings | ✅ pass |
| Ceiling sensitivity (headroom) | |
| Ceiling freshness (checkout vs. base branch) | ✅ pass |
⚠️ A broken gauge half is a verdict about the ceiling, not about the bundle: that line has drifted out of range of the regression it exists to catch, or the report behind it cannot be trusted. It does not say anything grew. TheCheck console performance budgetstep log carries the ceiling and the number it was compared against.
Reason: The entry chunk measured 144.3 KB, but the eager-closure half of this gate returned no trustworthy VERDICT: the report could not be read, a ceiling has drifted out of range of the regression it must catch, or (objectui#6245) a ceiling was replaced on the base branch after this checkout was made. The step log says which. This is not a passing budget — and it is not a size regression either.
See the workflow run for details.
📦 Bundle Size Report
| Package | Size | Gzipped |
|---|---|---|
| app-shell (consoleActionDispatch.js) | 0.20KB | 0.19KB |
| app-shell (index.js) | 16.69KB | 6.21KB |
| app-shell (runtime-config.js) | 20.68KB | 7.36KB |
| app-shell (types.js) | 0.01KB | 0.04KB |
| app-shell (urlParams.js) | 10.06KB | 3.86KB |
| auth (ActiveOrganizationStorage.js) | 25.05KB | 9.16KB |
| auth (AuthContext.js) | 0.31KB | 0.24KB |
| auth (AuthGuard.js) | 2.07KB | 1.00KB |
| auth (AuthProvider.js) | 40.18KB | 10.59KB |
| auth (AuthShell.js) | 3.49KB | 1.40KB |
| auth (ForgotPasswordForm.js) | 12.21KB | 3.45KB |
| auth (LoginForm.js) | 18.15KB | 5.39KB |
| auth (PreviewBanner.js) | 0.90KB | 0.50KB |
| auth (RegisterForm.js) | 6.65KB | 2.22KB |
| auth (SocialSignInButtons.js) | 9.61KB | 3.89KB |
| auth (UserMenu.js) | 3.41KB | 1.23KB |
| auth (auth-gate-events.js) | 1.29KB | 0.66KB |
| auth (authStyles.js) | 5.04KB | 1.72KB |
| auth (createAuthClient.js) | 40.21KB | 10.80KB |
| auth (createAuthenticatedFetch.js) | 8.46KB | 3.43KB |
| auth (index.js) | 3.19KB | 1.44KB |
| auth (invitation-status.js) | 1.22KB | 0.70KB |
| auth (org-roles.js) | 6.66KB | 2.78KB |
| auth (phone-identifier.js) | 1.11KB | 0.66KB |
| auth (types.js) | 0.59KB | 0.35KB |
| auth (useAuth.js) | 5.30KB | 1.02KB |
| auth (useWorkspaceAdminStatus.js) | 11.08KB | 4.58KB |
| collaboration (CommentThread.js) | 26.08KB | 7.56KB |
| collaboration (LiveCursors.js) | 3.17KB | 1.27KB |
| collaboration (PresenceAvatars.js) | 6.49KB | 2.64KB |
| collaboration (PresenceProvider.js) | 2.79KB | 1.13KB |
| collaboration (index.js) | 1.68KB | 0.73KB |
| collaboration (useCollaborationTranslation.js) | 6.05KB | 2.52KB |
| collaboration (useCommentSearch.js) | 1.98KB | 0.88KB |
| collaboration (useConflictResolution.js) | 7.75KB | 1.86KB |
| collaboration (useMentionNotifications.js) | 1.81KB | 0.68KB |
| collaboration (usePresence.js) | 6.33KB | 1.84KB |
| collaboration (useRealtimeSubscription.js) | 7.91KB | 2.01KB |
| components (index.js) | 502.02KB | 115.16KB |
| core (index.js) | 8.52KB | 3.41KB |
| create-plugin (index.js) | 27.94KB | 9.51KB |
| data-objectstack (index.js) | 211.58KB | 58.68KB |
| fields (index.js) | 247.89KB | 62.50KB |
| i18n (LocalizationContext.js) | 1.76KB | 0.96KB |
| i18n (builtinAggregateLabels.js) | 0.86KB | 0.49KB |
| i18n (currency.js) | 1.22KB | 0.64KB |
| i18n (fallbackInterpolation.js) | 6.25KB | 2.77KB |
| i18n (i18n.js) | 8.87KB | 3.64KB |
| i18n (index.js) | 5.22KB | 2.26KB |
| i18n (pickLocalized.js) | 9.86KB | 3.95KB |
| i18n (provider.js) | 32.15KB | 10.49KB |
| i18n (useDisplayLocale.js) | 2.85KB | 1.45KB |
| i18n (useObjectLabel.js) | 34.34KB | 9.17KB |
| i18n (useSafeTranslation.js) | 5.60KB | 2.33KB |
| layout (index.js) | 38.83KB | 10.95KB |
| mobile (MobileProvider.js) | 0.92KB | 0.49KB |
| mobile (ResponsiveContainer.js) | 0.94KB | 0.38KB |
| mobile (breakpoints.js) | 1.51KB | 0.70KB |
| mobile (createOfflineDataSource.js) | 5.61KB | 1.75KB |
| mobile (index.js) | 1.99KB | 0.87KB |
| mobile (offlineQueue.js) | 3.91KB | 1.35KB |
| mobile (pwa.js) | 0.97KB | 0.49KB |
| mobile (serviceWorker.js) | 1.48KB | 0.62KB |
| mobile (serviceWorkerSource.js) | 3.41KB | 1.48KB |
| mobile (useBreakpoint.js) | 1.54KB | 0.65KB |
| mobile (useGesture.js) | 6.96KB | 1.98KB |
| mobile (useOfflineSync.js) | 1.99KB | 0.72KB |
| mobile (usePullToRefresh.js) | 2.53KB | 0.85KB |
| mobile (useResponsive.js) | 0.72KB | 0.42KB |
| mobile (useSpecGesture.js) | 4.39KB | 1.66KB |
| mobile (useTouchTarget.js) | 1.01KB | 0.54KB |
| permissions (MePermissionsProvider.js) | 13.52KB | 4.88KB |
| permissions (PermissionContext.js) | 0.31KB | 0.25KB |
| permissions (PermissionGuard.js) | 0.89KB | 0.45KB |
| permissions (PermissionProvider.js) | 6.24KB | 2.16KB |
| permissions (discardProofCache.js) | 1.04KB | 0.55KB |
| permissions (evaluator.js) | 8.39KB | 3.10KB |
| permissions (index.js) | 0.93KB | 0.41KB |
| permissions (store.js) | 0.91KB | 0.42KB |
| permissions (useFieldPermissions.js) | 1.28KB | 0.53KB |
| permissions (usePermissions.js) | 4.83KB | 2.27KB |
| plugin-ai (index.js) | 14.81KB | 3.63KB |
| plugin-calendar (index.js) | 49.25KB | 13.99KB |
| plugin-charts (index.js) | 71.34KB | 19.90KB |
| plugin-chatbot (index.js) | 195.34KB | 46.51KB |
| plugin-dashboard (index.js) | 131.22KB | 34.59KB |
| plugin-designer (index.js) | 215.94KB | 44.33KB |
| plugin-detail (index.js) | 253.46KB | 65.85KB |
| plugin-editor (index.js) | 2.23KB | 1.05KB |
| plugin-form (index.js) | 136.77KB | 34.17KB |
| plugin-gantt (index.js) | 166.95KB | 41.04KB |
| plugin-grid (index.js) | 211.66KB | 57.50KB |
| plugin-kanban (index.js) | 46.00KB | 14.30KB |
| plugin-list (index.js) | 112.58KB | 27.65KB |
| plugin-map (index.js) | 20.64KB | 6.86KB |
| plugin-markdown (index.js) | 13.88KB | 4.80KB |
| plugin-report (index.js) | 43.41KB | 11.93KB |
| plugin-timeline (index.js) | 30.07KB | 8.74KB |
| plugin-tree (index.js) | 9.55KB | 3.32KB |
| plugin-view (index.js) | 84.42KB | 20.79KB |
| providers (DataSourceProvider.js) | 0.75KB | 0.39KB |
| providers (MetadataProvider.js) | 1.37KB | 0.59KB |
| providers (ThemeProvider.js) | 1.90KB | 0.85KB |
| providers (UploadProvider.js) | 11.66KB | 3.50KB |
| providers (index.js) | 0.45KB | 0.23KB |
| providers (types.js) | 0.01KB | 0.04KB |
| react-runtime (index.js) | 5.62KB | 2.34KB |
| react (LazyPluginLoader.js) | 4.47KB | 1.63KB |
| react (SchemaRenderer.js) | 96.00KB | 31.71KB |
| react (data-invalidation.js) | 5.05KB | 2.08KB |
| react (index.js) | 4.63KB | 2.18KB |
| react (schema-input.js) | 4.25KB | 2.04KB |
| react (spec-input.js) | 0.20KB | 0.18KB |
| sdui-parser (codegen.js) | 6.58KB | 2.74KB |
| sdui-parser (dashboard-widget-options.js) | 3.08KB | 1.30KB |
| sdui-parser (index.js) | 5.66KB | 2.50KB |
| sdui-parser (input-type.js) | 2.84KB | 1.40KB |
| sdui-parser (kanban-quick-add.js) | 3.89KB | 1.87KB |
| sdui-parser (parse.js) | 25.28KB | 7.80KB |
| sdui-parser (provenance.js) | 3.66KB | 1.82KB |
| sdui-parser (types.js) | 0.28KB | 0.23KB |
| sdui-parser (validate.js) | 14.82KB | 4.99KB |
| types (ai.js) | 0.20KB | 0.17KB |
| types (api-types.js) | 0.20KB | 0.18KB |
| types (app.js) | 2.87KB | 1.00KB |
| types (base.js) | 0.20KB | 0.18KB |
| types (blocks.js) | 0.20KB | 0.18KB |
| types (complex.js) | 2.93KB | 1.49KB |
| types (crud.js) | 0.20KB | 0.18KB |
| types (dashboard-filter-alias.js) | 6.23KB | 2.74KB |
| types (data-display.js) | 3.75KB | 1.85KB |
| types (data-protocol.js) | 0.20KB | 0.19KB |
| types (data.js) | 0.20KB | 0.18KB |
| types (designer.js) | 1.85KB | 0.85KB |
| types (disclosure.js) | 0.20KB | 0.18KB |
| types (error-code.js) | 1.54KB | 0.88KB |
| types (expression.js) | 0.20KB | 0.18KB |
| types (feedback.js) | 0.20KB | 0.18KB |
| types (field-types.js) | 0.20KB | 0.18KB |
| types (form.js) | 0.20KB | 0.18KB |
| types (http-inflight.js) | 8.87KB | 3.73KB |
| types (http-retry.js) | 4.32KB | 2.02KB |
| types (icon-key-migration.js) | 4.26KB | 1.63KB |
| types (index.js) | 4.74KB | 2.25KB |
| types (layout.js) | 0.20KB | 0.18KB |
| types (managed-by.js) | 0.19KB | 0.18KB |
| types (mobile.js) | 4.73KB | 2.28KB |
| types (navigation.js) | 0.20KB | 0.18KB |
| types (objectql.js) | 0.20KB | 0.18KB |
| types (overlay.js) | 0.20KB | 0.18KB |
| types (permissions.js) | 0.20KB | 0.18KB |
| types (plugin-scope.js) | 0.20KB | 0.18KB |
| types (record-components.js) | 0.20KB | 0.19KB |
| types (record-semantics.js) | 1.28KB | 0.67KB |
| types (registry.js) | 0.20KB | 0.18KB |
| types (reports.js) | 0.20KB | 0.18KB |
| types (select-option.js) | 0.20KB | 0.19KB |
| types (spec-report.js) | 5.05KB | 1.93KB |
| types (spec-ui-namespace.js) | 0.20KB | 0.19KB |
| types (strict-authoring-face.js) | 14.04KB | 5.36KB |
| types (system-fields.js) | 3.33KB | 1.54KB |
| types (theme.js) | 6.28KB | 2.87KB |
| types (ui-action.js) | 8.11KB | 3.32KB |
| types (views.js) | 0.20KB | 0.18KB |
| types (widget.js) | 0.20KB | 0.18KB |
Size Limits
- ✅ Core packages should be < 50KB gzipped
- ✅ Component packages should be < 100KB gzipped
⚠️ Plugin packages should be < 150KB gzipped
|
| reading | card said | measured then |
|---|---|---|
objectui refs to fieldRuleRootIssue / FIELD_RULE_BOUND_ROOTS under packages/ |
0 | 0 |
rowCanonAdvisory |
celAuthoring.ts:184-283 |
celAuthoring.ts:271 |
FIELD_RULE_BOUND_ROOTS export |
validate-expressions.ts:688 |
:680 |
fieldRuleRootIssue export |
validate-expressions.ts:790 |
:782 |
5651747919 — the os-dev-report, status: done, pushed c931579b3f, premise still valid, with
the zero backed by a lit control (rowCanonAdvisory 4 hits) so 「not used」 is a reading and not a
broken grep.
5652798679 — this seat's carrier repair adding the standalone Branch: line, part of the
board-wide seat-template fault that hit 13 cards.
⇒ the subject of the card is 「rowCanonAdvisory re-derives a verdict @objectstack/lint already
publishes」, and its tier is default.
What this seat is doing, and not doing
⛔ Not filing a replacement card: re-filing would fork the history and the original may be
restorable — GitHub issue deletion is an admin action and this seat cannot see who took it or undo it.
⛔ Not stripping Fixes #9318 from the body, and ⛔ not reviewing or landing this PR while its carrier
is missing.
For the maintainer, two questions, both one word:
- Can objectui#9318 be restored? If yes, nothing else here needs doing.
- If not, should this seat re-file it from the salvaged record above, and does the new number
replace theFixesreference?
The PR itself is otherwise healthy: Fixes #9318, 6 files, 32 of 36 checks green, and its only red is
the board-wide ui-components Bundle Analysis debt being paid down on objectui#9251 / PR
objectui#9399.
Generated by Claude Code
Card rebuilt — this PR's
|
Fixes #9440
rowCanonAdvisoryanswered "is this root bound on this surface?" from objectui's ownknowledge.
@objectstack/lintpublishes the same judgement. Two hand-maintained copies ofone verdict, agreeing today, with nothing keeping them agreeing.
Re-measurement — both sides, at implementation time
The card instructs that the re-measurement wins over the card. Both sets of line numbers
moved; the exported shape did not, so the substance survives intact.
9c44eed4/d7f0601)fieldRuleRootIssue/FIELD_RULE_BOUND_ROOTSunderpackages/git grepexit 1; controlrowCanonAdvisoryexit 0, 4 hits)rowCanonAdvisorycelAuthoring.ts:184-283celAuthoring.ts:271on objectuiorigin/main2e471dc0aFIELD_RULE_BOUND_ROOTSexportvalidate-expressions.ts:688:688on objectstackorigin/main2b6a207fieldRuleRootIssueexportvalidate-expressions.ts:790:790on objectstackorigin/main2b6a207@objectstack/lint@17.4.0, installed; both symbols on the package root entryOne correction to the dispatch note, offered as a reading and not a complaint: the
:680/:782figures are the sibling checkout's localHEAD(86c5052, an ancestor oforigin/main), notorigin/mainitself. Againstorigin/mainthe card's own:688/:790still hold. Either way the line numbers are informational — what this PR consumes isthe published
distof@objectstack/lint@17.4.0, where the declared shape readsFIELD_RULE_BOUND_ROOTS: readonly ["record", "previous", "parent"]andfieldRuleRootIssue(slot: string, source: string).Part 3 — the slot vocabulary does NOT cover every surface, and the fallback stays
This is the part the card most wants answered, so it is answered first and explicitly.
fieldRuleRootIssuejudges againstFIELD_RULE_BOUND_ROOTS— the FIELD-RULE tier,record/previous/parent. The surfacesrowCanonAdvisoryguards are everything thatreaches
lintCelPredicateatscope: 'record'. Measured, they do not share one bound set:visibleWhen/readonlyWhen/requiredWhen*WhenkeysFIELD_RULE_ROOTS=record,previous,parentvalidateObjectFieldRulesformulaexpressionexpression, rolevalueFORMULA_ROOTS=recordconditionconditionROW_PREDICATE_ROOTS=record,current_user,user,features,os,ctxThe two misses fail in opposite directions, which is why neither can be waved through:
previous.*/parent.*on a surface that binds neither — a silent coverage shrink, exactly what the card forbids;
current_user.isAdmin, a predicate that works there.So those two keep the local instrument, byte-for-byte as it behaves today, and each is pinned
as a live control that reddens if a later tidy-up routes them through the helper anyway.
Ablation leg B1 below performs that exact tidy-up and shows both controls going red.
PermissionAdvancedFacets(RLSUSING/CHECK) andConditionBuilderdefault toscope: 'flattened'and were never guarded by this advisory at all.What changed
CelSchemaHint.slot(and the matchingCelPredicateFieldprop) names the authored key. On acovered slot the verdict and the message are the helper's; everywhere else the local path
runs unchanged. Exactly one message ships per finding — never both.
The engine's message is taken rather than objectui's because objectui's single sentence is
per-root wrong once the verdict widens: "Re-root the reference on
record" is right fordataand actively harmful forcurrent_userorapp, which are not fields of the record.The engine's message refuses that rewrite by name.
Declared behaviour change. Those three editors now advise on every root the field level
leaves unbound, not only
data— the substance of adopting the published verdict. Severitystays objectui's own
warning: every save gate on this tier countsseverity === 'error', sono accept set moves and nothing already stored in customer metadata is refused. The
data.status == 'x'case still reports atwarning, nevererror.Progressive enhancement is preserved throughout — the
import()stays dynamic (a static onewould pull the lint bundle onto the eager console graph, objectui#5266), the export is
feature-detected, and a lint package without it falls through to the local instrument rather
than going quiet.
Not reopened
The three fences the card sets are untouched: objectui already warns on wrong-layer
data.*and still does; the advisory stays
warningand is never promoted; the bare-shorthand armstays disabled (
row = null) on the fallback path, and the helper path has no such arm at all.Red-first, verbatim
The pin was written and run on the unmodified tree first:
Ablation — three legs, all falsifiable, no null results
Every leg mutates on disk, proves the mutation reached disk before any result is read, and
restores by hash equality, never by an exit code. All ran under
trap ... EXIT INT TERM.Leg A — does the verdict really come from the published constant? Mutated the installed
@objectstack/lint@17.4.0dist/index.jsto dropparentfromFIELD_RULE_BOUND_ROOTS.The reading:
parent.status == "paid"atvisibleWhenis immediately advised, carrying theengine's own message ("
visibleWhenreadsparent, but a field-level conditional rule bindsonly
record…"). That is the card's required demonstration — a root the platform DOES bindcomes back clean through the new path, and stops being clean the moment the platform stops
binding it. The file is not git-tracked, so the restore proof is sha256 equality against the
pristine snapshot plus the anchor counts, and
git statuson the worktree is empty.Leg B1 — can the part-3 live controls fail? Replaced the slot condition with an
unconditional one, i.e. performed the exact tidy-up the card warns against.
Leg B2 — is the helper path actually reached? Emptied the covered-slot list.
No leg was a null result. All three could fail and all three did.
Verification
Acceptance grep:
git grep -c fieldRuleRootIssue packages/app-shell/srcexits 0 withpackages/app-shell/src/views/metadata-admin/celAuthoring.ts:8— non-zero.objectui#8972's five pins are green and byte-unchanged: the pin file's blob hash equals its
origin/mainblob (dbfc2108221cf22955927ac565804abdc3b4a1edboth sides), andcelAuthoring.test.tsreportsTests 39 passed (39).Heavy runs went through the shared verify lock on slot
os-dev-objectui-9318:The one skip is pre-existing; no test was skipped, quarantined or loosened by this change.
Gate family, derived by hand from
package.jsonplus.github/workflows/(this repo has nodispatch-gates deriver), all exit 0:
check:control-bytes,check:designer-field-key-parity,check:i18n-keys,check:phantom-deps,check:unreferenced-sources,check:test-path-roots,check:new-line-citations,check:changeset-claims,check:eager-closure,check:vi-mock-specifiers,check:vi-mock-inherit,check:vi-mock-override-shape,check:self-import,check-changeset-presence.mjs,check-governed-queue-guard.mjs --test(NOT GOVERNED, 6 paths against 5 surfaces).
Lint was run over the whole tree rather than narrowed:
pnpm exec eslint . --format jsonoverthe population eslint's own config selects — 4920 files, 0 errors, 12879 pre-existing
warnings. The five touched files carry 0 errors; their 12 warnings are pre-existing
no-explicit-anyandset-state-in-effectsites this change neither adds to nor moves.Dependent-set membership read, done here rather than inherited. Three different lists in
this repo share the word "exclude" and are NOT the same set:
.changeset/config.jsonignore=@object-ui/example-*,@object-ui/site,@object-ui/test-support— excluded from version bumping only;@object-ui/app-shell=@object-ui/console,@object-ui/example-byo-backend-console,@object-ui/example-console-starter— measured byreading every workspace manifest for a dependency edge on
@object-ui/app-shell;--filter=!@object-ui/site.@object-ui/sitesits in the first and the third and has no dependency edge onapp-shell, so it is not in the second at all; the genuine overlap between the first two is@object-ui/example-*.pnpm type-checkwas run in full, so all three dependents are coveredregardless.
@object-ui/app-shellis in the singlefixedgroup of 40, so a changeset isrequired and one is included (
minor;majoris unavailable to a fixed group of that size).Clause-② — still
no, verified rather than assumedNo exported signature of
@object-ui/app-shellmoves.CelSchemaHint,CelPredicateField,celAuthoring,rowCanonAdvisoryandFIELD_RULE_VERDICT_SLOTSeach appear 0 times inthe built
packages/app-shell/dist/index.d.ts, against a lit control (MetadataResourceRouter,1 hit) proving the grep and the file. The package's
exportsmap has a single entry. Nothingfor me to hang, and I have hung nothing.
Inherited red, not mine
maincarries two red checks — Doc Snippet Type Check and Skill Example Check —inherited by every PR whose CI runs against it. They are not this PR's: this diff touches no
file under
content/docs/orskills/, and both repairs are with the maintainer.Acceptance notes
Noted while reading, deliberately not filed and not repaired here:
clientValidation.validateObjectFieldRuleskeeps onlyseverity === 'error', so theadvisory it now asks for is discarded the moment it is produced. That is correct for a draft
gate and is stated in its own docblock; the slot is wired there anyway so the two
scope: 'record'callers ask the same authority the same question. An observation, not adefect — nothing is wrong today and no reader is misled.
FIELD_RULE_SLOT_CONSEQUENCE's slot vocabulary is module-private upstream, so a consumercannot ask
@objectstack/lintwhich slots it covers and must state its own answer, as thisPR does in
FIELD_RULE_VERDICT_SLOTS. A drift tripwire pins the bound set so the nextplatform move arrives as a red test here rather than as silence. Worth an upstream export
one day; nothing is broken, so no card. Carrier for that observation: none — no queued PR or
seat is touching that file.
Session:
https://claude.ai/code/session_01UzHd6hDYatoDn17BuwKxnZGenerated by Claude Code