fix(app-shell): diagnose non-literal elements in predicate in sets - #5265

Merged
os-support-ai merged 1 commit into
mainfrom
claude/issue-4266-in-predicate-array-diagnostic
Aug 18, 2026
Merged

fix(app-shell): diagnose non-literal elements in predicate in sets#5265
os-support-ai merged 1 commit into
mainfrom
claude/issue-4266-in-predicate-array-diagnostic

Conversation

@os-support-ai

Copy link
Copy Markdown
Collaborator

Fixes#4266

What

predicate.ts's in [...] array branch JSON-parses the bracketed text and, on any parse failure (a non-literal element — a path, a bare identifier, a trailing comma), the catch returned [] with nothing in the console. [].includes(anything) is false, so the predicate silently read FALSE FOR EVERY ROW — and because the parse is whole-set, not per-element, one bad element discarded every good literal sitting next to it too: data.type in ['text', data.a] collapsed exactly as hard as data.type in [data.a] alone.

Fix

Diagnose only, zero semantic change — the ruling this card asked me to measure against #4049's precedent, and matched it: the catch still returns []; an in set that fails to parse is still, and remains, the empty set. A dev-mode console.warn now names the predicate and, best-effort, the element that broke the parse (findUnparseableSetElement, which re-parses each top-level comma-separated element with the same quote-normalising JSON.parse the array branch already uses — for the warning text only, never to change the return value). Falls back to naming the whole set when no single element is individually at fault (e.g. a bare trailing comma). Warn-once keyed on (raw set text, predicate), same discipline as the two existing diagnostics in this file (#6936, #4049).

⛔ Does not widen the declared subset — a path inside in [...] still does not resolve; it is still reported as broken, just no longer silently.

A louder alternative (throw so the whole predicate fails open true, mirroring #6936) was considered and rejected — see the new header section in predicate.ts for the reasoning: false here is the documented behavior for an unparseable set, not a bug the way an unresolved path was, so flipping it to fail-open would be an unruled semantic change.

Premise re-verification

Triage verified on origin/main @ b954120 (a week old). Re-verified on current main @ bc2922a8 (post the two merges from #5227/PR5263 that touched widgets.tsx/loadState.ts in the same directory) — the array branch and its whole-set catch { return []; } were still exactly as described. Also checked whether ROADMAP M9 (real CEL) has landed: @objectstack/formula's cel-engine.ts exists and is already used elsewhere in app-shell (ExpressionProvider.tsx, celAuthoring.ts, clientValidation.ts, …), but SchemaForm.tsx is still the sole consumer of predicate.ts's evaluatePredicate — M9 has not replaced this specific evaluator, so the card is live.

Tests

predicate.test.ts §8 (new): non-literal element fires + names it (bare identifier, path-shaped, amid good literals, trailing-comma fallback), warn-once per (predicate, set) pair, dev-mode-only, and a §8.3 zero-semantics table pinning verdicts identical to the pre-fix [] shape — the same proof-shape as #4049's §7.3. §8.4 pins literal-only in sets completely unaffected (same verdict, silent).

Reverse-verification: restored the pre-fix two-line catch { return []; }, predicted exactly the 6 new assertions that reference the warning would go red (the two toHaveBeenCalledTimes warn-count tests and the four toContain(...) on warning text) while the rest of the file (88 tests, including the new §8.3/§8.4 verdict-only pins) stays green. Observed: exactly those 6 red, 88 green — restored the fix afterward from the committed branch state and re-ran to confirm 94/94 green again.

Gates run locally

  • pnpm --filter '@object-ui/app-shell^...' build (dependency closure) — clean
  • pnpm exec vitest run packages/app-shell/src/views/metadata-admin/predicate.test.ts — 94/94 passed (run from repo root per the package-level-vitest guard in this repo, objectui#3378)
  • pnpm --filter @object-ui/app-shell type-check — clean
  • pnpm --filter @object-ui/app-shell exec eslint src/views/metadata-admin/predicate.ts src/views/metadata-admin/predicate.test.ts — 0 errors (1 pre-existing no-explicit-any warning, unrelated line in resolveValue)
  • node scripts/check-control-bytes.mjs + explicit control-byte grep on both changed files — clean
  • node scripts/check-changeset-presence.mjs — 1 changeset present for the 1 released package touched
  • i18n gates (check:i18n-keys/check:i18n-drift): N/A — this diagnostic is a dev-mode console.warn, same as the two existing diagnostics in this file, neither of which goes through t()/i18n

Final commit: bb75ca165.


Generated by Claude Code

An `in` predicate's array branch JSON-parses the bracketed text and
returns an empty array on any parse failure, with no diagnostic. A
non-literal element (a path, a bare identifier, a trailing comma) collapses
the WHOLE set to [], so membership silently reads false for every row --
even discarding good literal elements sitting next to the bad one.
Diagnose only, mirroring objectui#4049's ruling: zero semantic change. The
catch still returns [], the verdict is untouched; a dev-mode console.warn
now names the predicate and, best-effort, the element that broke the parse.
Fixes#4266
@github-actions

Copy link
Copy Markdown
Contributor

✅ Console Performance Budget

MetricValueBudget
Main entry (gzip)25.3 KB350 KB
Entry fileindex-DGBVb25P.js
StatusPASS

📦 Bundle Size Report

PackageSizeGzipped
app-shell (index.js)9.83KB3.70KB
app-shell (runtime-config.js)7.42KB2.32KB
app-shell (types.js)0.01KB0.04KB
app-shell (urlParams.js)8.92KB3.41KB
auth (AuthContext.js)0.31KB0.24KB
auth (AuthGuard.js)1.17KB0.53KB
auth (AuthProvider.js)29.33KB7.05KB
auth (AuthShell.js)3.49KB1.40KB
auth (ForgotPasswordForm.js)12.21KB3.45KB
auth (LoginForm.js)18.13KB5.39KB
auth (PreviewBanner.js)0.90KB0.50KB
auth (RegisterForm.js)6.64KB2.21KB
auth (SocialSignInButtons.js)9.60KB3.89KB
auth (UserMenu.js)3.40KB1.22KB
auth (auth-gate-events.js)1.29KB0.66KB
auth (authStyles.js)5.04KB1.72KB
auth (createAuthClient.js)40.21KB10.79KB
auth (createAuthenticatedFetch.js)6.34KB2.43KB
auth (index.js)2.71KB1.22KB
auth (invitation-status.js)1.22KB0.70KB
auth (org-roles.js)6.66KB2.78KB
auth (phone-identifier.js)1.11KB0.66KB
auth (types.js)0.59KB0.35KB
auth (useAuth.js)5.02KB0.88KB
auth (useIsWorkspaceAdmin.js)1.61KB0.85KB
collaboration (CommentThread.js)26.07KB7.56KB
collaboration (LiveCursors.js)3.17KB1.27KB
collaboration (PresenceAvatars.js)6.49KB2.64KB
collaboration (PresenceProvider.js)2.79KB1.13KB
collaboration (index.js)1.65KB0.73KB
collaboration (useCollaborationTranslation.js)6.05KB2.52KB
collaboration (useCommentSearch.js)1.98KB0.88KB
collaboration (useConflictResolution.js)7.75KB1.86KB
collaboration (useMentionNotifications.js)1.81KB0.68KB
collaboration (usePresence.js)6.33KB1.84KB
collaboration (useRealtimeSubscription.js)7.91KB2.01KB
components (index.js)506.17KB113.33KB
core (index.js)4.11KB1.62KB
create-plugin (index.js)10.08KB3.26KB
data-objectstack (index.js)159.03KB44.08KB
fields (index.js)237.07KB59.46KB
i18n (LocalizationContext.js)1.76KB0.96KB
i18n (currency.js)1.22KB0.64KB
i18n (i18n.js)4.28KB1.75KB
i18n (index.js)3.42KB1.39KB
i18n (pickLocalized.js)3.69KB1.73KB
i18n (provider.js)23.13KB7.63KB
i18n (useDisplayLocale.js)2.85KB1.45KB
i18n (useObjectLabel.js)29.43KB7.15KB
i18n (useSafeTranslation.js)7.77KB3.13KB
layout (index.js)39.16KB10.97KB
mobile (MobileProvider.js)0.92KB0.49KB
mobile (ResponsiveContainer.js)0.94KB0.38KB
mobile (breakpoints.js)1.51KB0.70KB
mobile (createOfflineDataSource.js)5.61KB1.74KB
mobile (index.js)1.50KB0.62KB
mobile (offlineQueue.js)3.91KB1.35KB
mobile (pwa.js)0.97KB0.49KB
mobile (serviceWorker.js)1.48KB0.62KB
mobile (serviceWorkerSource.js)3.41KB1.48KB
mobile (useBreakpoint.js)1.54KB0.65KB
mobile (useGesture.js)6.96KB1.98KB
mobile (useOfflineSync.js)1.99KB0.72KB
mobile (usePullToRefresh.js)2.53KB0.85KB
mobile (useResponsive.js)0.71KB0.42KB
mobile (useResponsiveConfig.js)1.36KB0.63KB
mobile (useSpecGesture.js)4.32KB1.64KB
mobile (useTouchTarget.js)1.01KB0.54KB
permissions (MePermissionsProvider.js)9.35KB3.31KB
permissions (PermissionContext.js)0.31KB0.25KB
permissions (PermissionGuard.js)0.89KB0.45KB
permissions (PermissionProvider.js)4.42KB1.42KB
permissions (evaluator.js)5.12KB1.74KB
permissions (index.js)0.91KB0.41KB
permissions (store.js)0.91KB0.42KB
permissions (useFieldPermissions.js)1.28KB0.52KB
permissions (usePermissions.js)1.81KB0.83KB
plugin-ai (index.js)15.75KB3.80KB
plugin-calendar (index.js)46.62KB12.83KB
plugin-charts (index.js)64.75KB18.37KB
plugin-chatbot (index.js)181.21KB43.14KB
plugin-dashboard (index.js)128.04KB32.75KB
plugin-designer (index.js)212.39KB42.83KB
plugin-detail (index.js)241.46KB60.56KB
plugin-editor (index.js)2.46KB1.10KB
plugin-form (index.js)123.77KB30.07KB
plugin-gantt (index.js)164.10KB39.87KB
plugin-grid (index.js)198.22KB53.27KB
plugin-kanban (index.js)52.93KB14.60KB
plugin-list (index.js)111.66KB27.13KB
plugin-map (index.js)19.96KB6.56KB
plugin-markdown (index.js)13.72KB4.69KB
plugin-report (index.js)42.84KB11.77KB
plugin-timeline (index.js)26.68KB7.66KB
plugin-tree (index.js)8.50KB2.88KB
plugin-view (index.js)84.08KB20.59KB
providers (DataSourceProvider.js)0.75KB0.39KB
providers (MetadataProvider.js)1.37KB0.59KB
providers (ThemeProvider.js)1.90KB0.85KB
providers (UploadProvider.js)11.66KB3.50KB
providers (index.js)0.44KB0.22KB
providers (types.js)0.01KB0.04KB
react-runtime (index.js)5.62KB2.34KB
react (LazyPluginLoader.js)3.77KB1.33KB
react (SchemaRenderer.js)31.56KB10.70KB
react (data-invalidation.js)5.05KB2.08KB
react (index.js)1.33KB0.69KB
react (schema-input.js)1.45KB0.83KB
react (spec-input.js)0.20KB0.18KB
sdui-parser (codegen.js)5.41KB2.34KB
sdui-parser (index.js)4.77KB2.16KB
sdui-parser (input-type.js)2.84KB1.40KB
sdui-parser (parse.js)10.76KB3.17KB
sdui-parser (provenance.js)3.66KB1.82KB
sdui-parser (types.js)0.29KB0.24KB
sdui-parser (validate.js)6.92KB2.40KB
types (ai.js)0.20KB0.17KB
types (api-types.js)0.20KB0.18KB
types (app.js)2.87KB0.99KB
types (base.js)0.20KB0.18KB
types (blocks.js)0.20KB0.18KB
types (complex.js)0.20KB0.18KB
types (crud.js)0.20KB0.18KB
types (dashboard-filter-alias.js)6.23KB2.74KB
types (data-display.js)0.20KB0.18KB
types (data-protocol.js)0.20KB0.19KB
types (data.js)0.20KB0.18KB
types (designer.js)1.87KB0.85KB
types (disclosure.js)0.20KB0.18KB
types (error-code.js)1.54KB0.88KB
types (feedback.js)0.20KB0.18KB
types (field-types.js)0.20KB0.18KB
types (form.js)0.20KB0.18KB
types (http-retry.js)4.32KB2.02KB
types (index.js)3.08KB1.53KB
types (layout.js)0.20KB0.18KB
types (managed-by.js)0.19KB0.18KB
types (mobile.js)2.59KB1.31KB
types (navigation.js)0.20KB0.18KB
types (objectql.js)0.20KB0.18KB
types (overlay.js)0.20KB0.18KB
types (permissions.js)0.20KB0.18KB
types (plugin-scope.js)0.20KB0.18KB
types (record-components.js)0.20KB0.19KB
types (record-semantics.js)1.28KB0.67KB
types (registry.js)0.20KB0.18KB
types (reports.js)0.20KB0.18KB
types (spec-report.js)5.05KB1.93KB
types (system-fields.js)3.33KB1.54KB
types (theme.js)0.20KB0.18KB
types (ui-action.js)3.40KB1.71KB
types (views.js)0.20KB0.18KB
types (widget.js)0.20KB0.18KB

Size Limits

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

@os-support-ai
os-support-ai marked this pull request as ready for review August 18, 2026 23:05
@os-support-ai
os-support-ai added this pull request to the merge queueAug 18, 2026
Merged via the queue into main with commit 2eb8db8Aug 18, 2026
22 checks passed
@os-support-ai
os-support-ai deleted the claude/issue-4266-in-predicate-array-diagnostic branch August 18, 2026 23:06
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

objectui: metadata-admin predicate in with a non-literal element silently becomes an empty set — membership false for every row, no diagnostic

2 participants

@os-support-ai@claude
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

fix(app-shell): diagnose non-literal elements in predicate in sets - #5265

Merged
os-support-ai merged 1 commit into
mainfrom
claude/issue-4266-in-predicate-array-diagnostic
Aug 18, 2026
Merged

fix(app-shell): diagnose non-literal elements in predicate in sets#5265
os-support-ai merged 1 commit into
mainfrom
claude/issue-4266-in-predicate-array-diagnostic

Conversation

@os-support-ai

Copy link
Copy Markdown
Collaborator

Fixes#4266

What

predicate.ts's in [...] array branch JSON-parses the bracketed text and, on any parse failure (a non-literal element — a path, a bare identifier, a trailing comma), the catch returned [] with nothing in the console. [].includes(anything) is false, so the predicate silently read FALSE FOR EVERY ROW — and because the parse is whole-set, not per-element, one bad element discarded every good literal sitting next to it too: data.type in ['text', data.a] collapsed exactly as hard as data.type in [data.a] alone.

Fix

Diagnose only, zero semantic change — the ruling this card asked me to measure against #4049's precedent, and matched it: the catch still returns []; an in set that fails to parse is still, and remains, the empty set. A dev-mode console.warn now names the predicate and, best-effort, the element that broke the parse (findUnparseableSetElement, which re-parses each top-level comma-separated element with the same quote-normalising JSON.parse the array branch already uses — for the warning text only, never to change the return value). Falls back to naming the whole set when no single element is individually at fault (e.g. a bare trailing comma). Warn-once keyed on (raw set text, predicate), same discipline as the two existing diagnostics in this file (#6936, #4049).

⛔ Does not widen the declared subset — a path inside in [...] still does not resolve; it is still reported as broken, just no longer silently.

A louder alternative (throw so the whole predicate fails open true, mirroring #6936) was considered and rejected — see the new header section in predicate.ts for the reasoning: false here is the documented behavior for an unparseable set, not a bug the way an unresolved path was, so flipping it to fail-open would be an unruled semantic change.

Premise re-verification

Triage verified on origin/main @ b954120 (a week old). Re-verified on current main @ bc2922a8 (post the two merges from #5227/PR5263 that touched widgets.tsx/loadState.ts in the same directory) — the array branch and its whole-set catch { return []; } were still exactly as described. Also checked whether ROADMAP M9 (real CEL) has landed: @objectstack/formula's cel-engine.ts exists and is already used elsewhere in app-shell (ExpressionProvider.tsx, celAuthoring.ts, clientValidation.ts, …), but SchemaForm.tsx is still the sole consumer of predicate.ts's evaluatePredicate — M9 has not replaced this specific evaluator, so the card is live.

Tests

predicate.test.ts §8 (new): non-literal element fires + names it (bare identifier, path-shaped, amid good literals, trailing-comma fallback), warn-once per (predicate, set) pair, dev-mode-only, and a §8.3 zero-semantics table pinning verdicts identical to the pre-fix [] shape — the same proof-shape as #4049's §7.3. §8.4 pins literal-only in sets completely unaffected (same verdict, silent).

Reverse-verification: restored the pre-fix two-line catch { return []; }, predicted exactly the 6 new assertions that reference the warning would go red (the two toHaveBeenCalledTimes warn-count tests and the four toContain(...) on warning text) while the rest of the file (88 tests, including the new §8.3/§8.4 verdict-only pins) stays green. Observed: exactly those 6 red, 88 green — restored the fix afterward from the committed branch state and re-ran to confirm 94/94 green again.

Gates run locally

  • pnpm --filter '@object-ui/app-shell^...' build (dependency closure) — clean
  • pnpm exec vitest run packages/app-shell/src/views/metadata-admin/predicate.test.ts — 94/94 passed (run from repo root per the package-level-vitest guard in this repo, objectui#3378)
  • pnpm --filter @object-ui/app-shell type-check — clean
  • pnpm --filter @object-ui/app-shell exec eslint src/views/metadata-admin/predicate.ts src/views/metadata-admin/predicate.test.ts — 0 errors (1 pre-existing no-explicit-any warning, unrelated line in resolveValue)
  • node scripts/check-control-bytes.mjs + explicit control-byte grep on both changed files — clean
  • node scripts/check-changeset-presence.mjs — 1 changeset present for the 1 released package touched
  • i18n gates (check:i18n-keys/check:i18n-drift): N/A — this diagnostic is a dev-mode console.warn, same as the two existing diagnostics in this file, neither of which goes through t()/i18n

Final commit: bb75ca165.


Generated by Claude Code

An `in` predicate's array branch JSON-parses the bracketed text and
returns an empty array on any parse failure, with no diagnostic. A
non-literal element (a path, a bare identifier, a trailing comma) collapses
the WHOLE set to [], so membership silently reads false for every row --
even discarding good literal elements sitting next to the bad one.
Diagnose only, mirroring objectui#4049's ruling: zero semantic change. The
catch still returns [], the verdict is untouched; a dev-mode console.warn
now names the predicate and, best-effort, the element that broke the parse.
Fixes#4266
@github-actions

Copy link
Copy Markdown
Contributor

✅ Console Performance Budget

MetricValueBudget
Main entry (gzip)25.3 KB350 KB
Entry fileindex-DGBVb25P.js
StatusPASS

📦 Bundle Size Report

PackageSizeGzipped
app-shell (index.js)9.83KB3.70KB
app-shell (runtime-config.js)7.42KB2.32KB
app-shell (types.js)0.01KB0.04KB
app-shell (urlParams.js)8.92KB3.41KB
auth (AuthContext.js)0.31KB0.24KB
auth (AuthGuard.js)1.17KB0.53KB
auth (AuthProvider.js)29.33KB7.05KB
auth (AuthShell.js)3.49KB1.40KB
auth (ForgotPasswordForm.js)12.21KB3.45KB
auth (LoginForm.js)18.13KB5.39KB
auth (PreviewBanner.js)0.90KB0.50KB
auth (RegisterForm.js)6.64KB2.21KB
auth (SocialSignInButtons.js)9.60KB3.89KB
auth (UserMenu.js)3.40KB1.22KB
auth (auth-gate-events.js)1.29KB0.66KB
auth (authStyles.js)5.04KB1.72KB
auth (createAuthClient.js)40.21KB10.79KB
auth (createAuthenticatedFetch.js)6.34KB2.43KB
auth (index.js)2.71KB1.22KB
auth (invitation-status.js)1.22KB0.70KB
auth (org-roles.js)6.66KB2.78KB
auth (phone-identifier.js)1.11KB0.66KB
auth (types.js)0.59KB0.35KB
auth (useAuth.js)5.02KB0.88KB
auth (useIsWorkspaceAdmin.js)1.61KB0.85KB
collaboration (CommentThread.js)26.07KB7.56KB
collaboration (LiveCursors.js)3.17KB1.27KB
collaboration (PresenceAvatars.js)6.49KB2.64KB
collaboration (PresenceProvider.js)2.79KB1.13KB
collaboration (index.js)1.65KB0.73KB
collaboration (useCollaborationTranslation.js)6.05KB2.52KB
collaboration (useCommentSearch.js)1.98KB0.88KB
collaboration (useConflictResolution.js)7.75KB1.86KB
collaboration (useMentionNotifications.js)1.81KB0.68KB
collaboration (usePresence.js)6.33KB1.84KB
collaboration (useRealtimeSubscription.js)7.91KB2.01KB
components (index.js)506.17KB113.33KB
core (index.js)4.11KB1.62KB
create-plugin (index.js)10.08KB3.26KB
data-objectstack (index.js)159.03KB44.08KB
fields (index.js)237.07KB59.46KB
i18n (LocalizationContext.js)1.76KB0.96KB
i18n (currency.js)1.22KB0.64KB
i18n (i18n.js)4.28KB1.75KB
i18n (index.js)3.42KB1.39KB
i18n (pickLocalized.js)3.69KB1.73KB
i18n (provider.js)23.13KB7.63KB
i18n (useDisplayLocale.js)2.85KB1.45KB
i18n (useObjectLabel.js)29.43KB7.15KB
i18n (useSafeTranslation.js)7.77KB3.13KB
layout (index.js)39.16KB10.97KB
mobile (MobileProvider.js)0.92KB0.49KB
mobile (ResponsiveContainer.js)0.94KB0.38KB
mobile (breakpoints.js)1.51KB0.70KB
mobile (createOfflineDataSource.js)5.61KB1.74KB
mobile (index.js)1.50KB0.62KB
mobile (offlineQueue.js)3.91KB1.35KB
mobile (pwa.js)0.97KB0.49KB
mobile (serviceWorker.js)1.48KB0.62KB
mobile (serviceWorkerSource.js)3.41KB1.48KB
mobile (useBreakpoint.js)1.54KB0.65KB
mobile (useGesture.js)6.96KB1.98KB
mobile (useOfflineSync.js)1.99KB0.72KB
mobile (usePullToRefresh.js)2.53KB0.85KB
mobile (useResponsive.js)0.71KB0.42KB
mobile (useResponsiveConfig.js)1.36KB0.63KB
mobile (useSpecGesture.js)4.32KB1.64KB
mobile (useTouchTarget.js)1.01KB0.54KB
permissions (MePermissionsProvider.js)9.35KB3.31KB
permissions (PermissionContext.js)0.31KB0.25KB
permissions (PermissionGuard.js)0.89KB0.45KB
permissions (PermissionProvider.js)4.42KB1.42KB
permissions (evaluator.js)5.12KB1.74KB
permissions (index.js)0.91KB0.41KB
permissions (store.js)0.91KB0.42KB
permissions (useFieldPermissions.js)1.28KB0.52KB
permissions (usePermissions.js)1.81KB0.83KB
plugin-ai (index.js)15.75KB3.80KB
plugin-calendar (index.js)46.62KB12.83KB
plugin-charts (index.js)64.75KB18.37KB
plugin-chatbot (index.js)181.21KB43.14KB
plugin-dashboard (index.js)128.04KB32.75KB
plugin-designer (index.js)212.39KB42.83KB
plugin-detail (index.js)241.46KB60.56KB
plugin-editor (index.js)2.46KB1.10KB
plugin-form (index.js)123.77KB30.07KB
plugin-gantt (index.js)164.10KB39.87KB
plugin-grid (index.js)198.22KB53.27KB
plugin-kanban (index.js)52.93KB14.60KB
plugin-list (index.js)111.66KB27.13KB
plugin-map (index.js)19.96KB6.56KB
plugin-markdown (index.js)13.72KB4.69KB
plugin-report (index.js)42.84KB11.77KB
plugin-timeline (index.js)26.68KB7.66KB
plugin-tree (index.js)8.50KB2.88KB
plugin-view (index.js)84.08KB20.59KB
providers (DataSourceProvider.js)0.75KB0.39KB
providers (MetadataProvider.js)1.37KB0.59KB
providers (ThemeProvider.js)1.90KB0.85KB
providers (UploadProvider.js)11.66KB3.50KB
providers (index.js)0.44KB0.22KB
providers (types.js)0.01KB0.04KB
react-runtime (index.js)5.62KB2.34KB
react (LazyPluginLoader.js)3.77KB1.33KB
react (SchemaRenderer.js)31.56KB10.70KB
react (data-invalidation.js)5.05KB2.08KB
react (index.js)1.33KB0.69KB
react (schema-input.js)1.45KB0.83KB
react (spec-input.js)0.20KB0.18KB
sdui-parser (codegen.js)5.41KB2.34KB
sdui-parser (index.js)4.77KB2.16KB
sdui-parser (input-type.js)2.84KB1.40KB
sdui-parser (parse.js)10.76KB3.17KB
sdui-parser (provenance.js)3.66KB1.82KB
sdui-parser (types.js)0.29KB0.24KB
sdui-parser (validate.js)6.92KB2.40KB
types (ai.js)0.20KB0.17KB
types (api-types.js)0.20KB0.18KB
types (app.js)2.87KB0.99KB
types (base.js)0.20KB0.18KB
types (blocks.js)0.20KB0.18KB
types (complex.js)0.20KB0.18KB
types (crud.js)0.20KB0.18KB
types (dashboard-filter-alias.js)6.23KB2.74KB
types (data-display.js)0.20KB0.18KB
types (data-protocol.js)0.20KB0.19KB
types (data.js)0.20KB0.18KB
types (designer.js)1.87KB0.85KB
types (disclosure.js)0.20KB0.18KB
types (error-code.js)1.54KB0.88KB
types (feedback.js)0.20KB0.18KB
types (field-types.js)0.20KB0.18KB
types (form.js)0.20KB0.18KB
types (http-retry.js)4.32KB2.02KB
types (index.js)3.08KB1.53KB
types (layout.js)0.20KB0.18KB
types (managed-by.js)0.19KB0.18KB
types (mobile.js)2.59KB1.31KB
types (navigation.js)0.20KB0.18KB
types (objectql.js)0.20KB0.18KB
types (overlay.js)0.20KB0.18KB
types (permissions.js)0.20KB0.18KB
types (plugin-scope.js)0.20KB0.18KB
types (record-components.js)0.20KB0.19KB
types (record-semantics.js)1.28KB0.67KB
types (registry.js)0.20KB0.18KB
types (reports.js)0.20KB0.18KB
types (spec-report.js)5.05KB1.93KB
types (system-fields.js)3.33KB1.54KB
types (theme.js)0.20KB0.18KB
types (ui-action.js)3.40KB1.71KB
types (views.js)0.20KB0.18KB
types (widget.js)0.20KB0.18KB

Size Limits

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

@os-support-ai
os-support-ai marked this pull request as ready for review August 18, 2026 23:05
@os-support-ai
os-support-ai added this pull request to the merge queueAug 18, 2026
Merged via the queue into main with commit 2eb8db8Aug 18, 2026
22 checks passed
@os-support-ai
os-support-ai deleted the claude/issue-4266-in-predicate-array-diagnostic branch August 18, 2026 23:06
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

objectui: metadata-admin predicate in with a non-literal element silently becomes an empty set — membership false for every row, no diagnostic

2 participants

@os-support-ai@claude
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

fix(app-shell): diagnose non-literal elements in predicate in sets - #5265

Merged
os-support-ai merged 1 commit into
mainfrom
claude/issue-4266-in-predicate-array-diagnostic
Aug 18, 2026
Merged

fix(app-shell): diagnose non-literal elements in predicate in sets#5265
os-support-ai merged 1 commit into
mainfrom
claude/issue-4266-in-predicate-array-diagnostic

Conversation

@os-support-ai

Copy link
Copy Markdown
Collaborator

Fixes#4266

What

predicate.ts's in [...] array branch JSON-parses the bracketed text and, on any parse failure (a non-literal element — a path, a bare identifier, a trailing comma), the catch returned [] with nothing in the console. [].includes(anything) is false, so the predicate silently read FALSE FOR EVERY ROW — and because the parse is whole-set, not per-element, one bad element discarded every good literal sitting next to it too: data.type in ['text', data.a] collapsed exactly as hard as data.type in [data.a] alone.

Fix

Diagnose only, zero semantic change — the ruling this card asked me to measure against #4049's precedent, and matched it: the catch still returns []; an in set that fails to parse is still, and remains, the empty set. A dev-mode console.warn now names the predicate and, best-effort, the element that broke the parse (findUnparseableSetElement, which re-parses each top-level comma-separated element with the same quote-normalising JSON.parse the array branch already uses — for the warning text only, never to change the return value). Falls back to naming the whole set when no single element is individually at fault (e.g. a bare trailing comma). Warn-once keyed on (raw set text, predicate), same discipline as the two existing diagnostics in this file (#6936, #4049).

⛔ Does not widen the declared subset — a path inside in [...] still does not resolve; it is still reported as broken, just no longer silently.

A louder alternative (throw so the whole predicate fails open true, mirroring #6936) was considered and rejected — see the new header section in predicate.ts for the reasoning: false here is the documented behavior for an unparseable set, not a bug the way an unresolved path was, so flipping it to fail-open would be an unruled semantic change.

Premise re-verification

Triage verified on origin/main @ b954120 (a week old). Re-verified on current main @ bc2922a8 (post the two merges from #5227/PR5263 that touched widgets.tsx/loadState.ts in the same directory) — the array branch and its whole-set catch { return []; } were still exactly as described. Also checked whether ROADMAP M9 (real CEL) has landed: @objectstack/formula's cel-engine.ts exists and is already used elsewhere in app-shell (ExpressionProvider.tsx, celAuthoring.ts, clientValidation.ts, …), but SchemaForm.tsx is still the sole consumer of predicate.ts's evaluatePredicate — M9 has not replaced this specific evaluator, so the card is live.

Tests

predicate.test.ts §8 (new): non-literal element fires + names it (bare identifier, path-shaped, amid good literals, trailing-comma fallback), warn-once per (predicate, set) pair, dev-mode-only, and a §8.3 zero-semantics table pinning verdicts identical to the pre-fix [] shape — the same proof-shape as #4049's §7.3. §8.4 pins literal-only in sets completely unaffected (same verdict, silent).

Reverse-verification: restored the pre-fix two-line catch { return []; }, predicted exactly the 6 new assertions that reference the warning would go red (the two toHaveBeenCalledTimes warn-count tests and the four toContain(...) on warning text) while the rest of the file (88 tests, including the new §8.3/§8.4 verdict-only pins) stays green. Observed: exactly those 6 red, 88 green — restored the fix afterward from the committed branch state and re-ran to confirm 94/94 green again.

Gates run locally

  • pnpm --filter '@object-ui/app-shell^...' build (dependency closure) — clean
  • pnpm exec vitest run packages/app-shell/src/views/metadata-admin/predicate.test.ts — 94/94 passed (run from repo root per the package-level-vitest guard in this repo, objectui#3378)
  • pnpm --filter @object-ui/app-shell type-check — clean
  • pnpm --filter @object-ui/app-shell exec eslint src/views/metadata-admin/predicate.ts src/views/metadata-admin/predicate.test.ts — 0 errors (1 pre-existing no-explicit-any warning, unrelated line in resolveValue)
  • node scripts/check-control-bytes.mjs + explicit control-byte grep on both changed files — clean
  • node scripts/check-changeset-presence.mjs — 1 changeset present for the 1 released package touched
  • i18n gates (check:i18n-keys/check:i18n-drift): N/A — this diagnostic is a dev-mode console.warn, same as the two existing diagnostics in this file, neither of which goes through t()/i18n

Final commit: bb75ca165.


Generated by Claude Code

An `in` predicate's array branch JSON-parses the bracketed text and
returns an empty array on any parse failure, with no diagnostic. A
non-literal element (a path, a bare identifier, a trailing comma) collapses
the WHOLE set to [], so membership silently reads false for every row --
even discarding good literal elements sitting next to the bad one.
Diagnose only, mirroring objectui#4049's ruling: zero semantic change. The
catch still returns [], the verdict is untouched; a dev-mode console.warn
now names the predicate and, best-effort, the element that broke the parse.
Fixes#4266
@github-actions

Copy link
Copy Markdown
Contributor

✅ Console Performance Budget

MetricValueBudget
Main entry (gzip)25.3 KB350 KB
Entry fileindex-DGBVb25P.js
StatusPASS

📦 Bundle Size Report

PackageSizeGzipped
app-shell (index.js)9.83KB3.70KB
app-shell (runtime-config.js)7.42KB2.32KB
app-shell (types.js)0.01KB0.04KB
app-shell (urlParams.js)8.92KB3.41KB
auth (AuthContext.js)0.31KB0.24KB
auth (AuthGuard.js)1.17KB0.53KB
auth (AuthProvider.js)29.33KB7.05KB
auth (AuthShell.js)3.49KB1.40KB
auth (ForgotPasswordForm.js)12.21KB3.45KB
auth (LoginForm.js)18.13KB5.39KB
auth (PreviewBanner.js)0.90KB0.50KB
auth (RegisterForm.js)6.64KB2.21KB
auth (SocialSignInButtons.js)9.60KB3.89KB
auth (UserMenu.js)3.40KB1.22KB
auth (auth-gate-events.js)1.29KB0.66KB
auth (authStyles.js)5.04KB1.72KB
auth (createAuthClient.js)40.21KB10.79KB
auth (createAuthenticatedFetch.js)6.34KB2.43KB
auth (index.js)2.71KB1.22KB
auth (invitation-status.js)1.22KB0.70KB
auth (org-roles.js)6.66KB2.78KB
auth (phone-identifier.js)1.11KB0.66KB
auth (types.js)0.59KB0.35KB
auth (useAuth.js)5.02KB0.88KB
auth (useIsWorkspaceAdmin.js)1.61KB0.85KB
collaboration (CommentThread.js)26.07KB7.56KB
collaboration (LiveCursors.js)3.17KB1.27KB
collaboration (PresenceAvatars.js)6.49KB2.64KB
collaboration (PresenceProvider.js)2.79KB1.13KB
collaboration (index.js)1.65KB0.73KB
collaboration (useCollaborationTranslation.js)6.05KB2.52KB
collaboration (useCommentSearch.js)1.98KB0.88KB
collaboration (useConflictResolution.js)7.75KB1.86KB
collaboration (useMentionNotifications.js)1.81KB0.68KB
collaboration (usePresence.js)6.33KB1.84KB
collaboration (useRealtimeSubscription.js)7.91KB2.01KB
components (index.js)506.17KB113.33KB
core (index.js)4.11KB1.62KB
create-plugin (index.js)10.08KB3.26KB
data-objectstack (index.js)159.03KB44.08KB
fields (index.js)237.07KB59.46KB
i18n (LocalizationContext.js)1.76KB0.96KB
i18n (currency.js)1.22KB0.64KB
i18n (i18n.js)4.28KB1.75KB
i18n (index.js)3.42KB1.39KB
i18n (pickLocalized.js)3.69KB1.73KB
i18n (provider.js)23.13KB7.63KB
i18n (useDisplayLocale.js)2.85KB1.45KB
i18n (useObjectLabel.js)29.43KB7.15KB
i18n (useSafeTranslation.js)7.77KB3.13KB
layout (index.js)39.16KB10.97KB
mobile (MobileProvider.js)0.92KB0.49KB
mobile (ResponsiveContainer.js)0.94KB0.38KB
mobile (breakpoints.js)1.51KB0.70KB
mobile (createOfflineDataSource.js)5.61KB1.74KB
mobile (index.js)1.50KB0.62KB
mobile (offlineQueue.js)3.91KB1.35KB
mobile (pwa.js)0.97KB0.49KB
mobile (serviceWorker.js)1.48KB0.62KB
mobile (serviceWorkerSource.js)3.41KB1.48KB
mobile (useBreakpoint.js)1.54KB0.65KB
mobile (useGesture.js)6.96KB1.98KB
mobile (useOfflineSync.js)1.99KB0.72KB
mobile (usePullToRefresh.js)2.53KB0.85KB
mobile (useResponsive.js)0.71KB0.42KB
mobile (useResponsiveConfig.js)1.36KB0.63KB
mobile (useSpecGesture.js)4.32KB1.64KB
mobile (useTouchTarget.js)1.01KB0.54KB
permissions (MePermissionsProvider.js)9.35KB3.31KB
permissions (PermissionContext.js)0.31KB0.25KB
permissions (PermissionGuard.js)0.89KB0.45KB
permissions (PermissionProvider.js)4.42KB1.42KB
permissions (evaluator.js)5.12KB1.74KB
permissions (index.js)0.91KB0.41KB
permissions (store.js)0.91KB0.42KB
permissions (useFieldPermissions.js)1.28KB0.52KB
permissions (usePermissions.js)1.81KB0.83KB
plugin-ai (index.js)15.75KB3.80KB
plugin-calendar (index.js)46.62KB12.83KB
plugin-charts (index.js)64.75KB18.37KB
plugin-chatbot (index.js)181.21KB43.14KB
plugin-dashboard (index.js)128.04KB32.75KB
plugin-designer (index.js)212.39KB42.83KB
plugin-detail (index.js)241.46KB60.56KB
plugin-editor (index.js)2.46KB1.10KB
plugin-form (index.js)123.77KB30.07KB
plugin-gantt (index.js)164.10KB39.87KB
plugin-grid (index.js)198.22KB53.27KB
plugin-kanban (index.js)52.93KB14.60KB
plugin-list (index.js)111.66KB27.13KB
plugin-map (index.js)19.96KB6.56KB
plugin-markdown (index.js)13.72KB4.69KB
plugin-report (index.js)42.84KB11.77KB
plugin-timeline (index.js)26.68KB7.66KB
plugin-tree (index.js)8.50KB2.88KB
plugin-view (index.js)84.08KB20.59KB
providers (DataSourceProvider.js)0.75KB0.39KB
providers (MetadataProvider.js)1.37KB0.59KB
providers (ThemeProvider.js)1.90KB0.85KB
providers (UploadProvider.js)11.66KB3.50KB
providers (index.js)0.44KB0.22KB
providers (types.js)0.01KB0.04KB
react-runtime (index.js)5.62KB2.34KB
react (LazyPluginLoader.js)3.77KB1.33KB
react (SchemaRenderer.js)31.56KB10.70KB
react (data-invalidation.js)5.05KB2.08KB
react (index.js)1.33KB0.69KB
react (schema-input.js)1.45KB0.83KB
react (spec-input.js)0.20KB0.18KB
sdui-parser (codegen.js)5.41KB2.34KB
sdui-parser (index.js)4.77KB2.16KB
sdui-parser (input-type.js)2.84KB1.40KB
sdui-parser (parse.js)10.76KB3.17KB
sdui-parser (provenance.js)3.66KB1.82KB
sdui-parser (types.js)0.29KB0.24KB
sdui-parser (validate.js)6.92KB2.40KB
types (ai.js)0.20KB0.17KB
types (api-types.js)0.20KB0.18KB
types (app.js)2.87KB0.99KB
types (base.js)0.20KB0.18KB
types (blocks.js)0.20KB0.18KB
types (complex.js)0.20KB0.18KB
types (crud.js)0.20KB0.18KB
types (dashboard-filter-alias.js)6.23KB2.74KB
types (data-display.js)0.20KB0.18KB
types (data-protocol.js)0.20KB0.19KB
types (data.js)0.20KB0.18KB
types (designer.js)1.87KB0.85KB
types (disclosure.js)0.20KB0.18KB
types (error-code.js)1.54KB0.88KB
types (feedback.js)0.20KB0.18KB
types (field-types.js)0.20KB0.18KB
types (form.js)0.20KB0.18KB
types (http-retry.js)4.32KB2.02KB
types (index.js)3.08KB1.53KB
types (layout.js)0.20KB0.18KB
types (managed-by.js)0.19KB0.18KB
types (mobile.js)2.59KB1.31KB
types (navigation.js)0.20KB0.18KB
types (objectql.js)0.20KB0.18KB
types (overlay.js)0.20KB0.18KB
types (permissions.js)0.20KB0.18KB
types (plugin-scope.js)0.20KB0.18KB
types (record-components.js)0.20KB0.19KB
types (record-semantics.js)1.28KB0.67KB
types (registry.js)0.20KB0.18KB
types (reports.js)0.20KB0.18KB
types (spec-report.js)5.05KB1.93KB
types (system-fields.js)3.33KB1.54KB
types (theme.js)0.20KB0.18KB
types (ui-action.js)3.40KB1.71KB
types (views.js)0.20KB0.18KB
types (widget.js)0.20KB0.18KB

Size Limits

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

@os-support-ai
os-support-ai marked this pull request as ready for review August 18, 2026 23:05
@os-support-ai
os-support-ai added this pull request to the merge queueAug 18, 2026
Merged via the queue into main with commit 2eb8db8Aug 18, 2026
22 checks passed
@os-support-ai
os-support-ai deleted the claude/issue-4266-in-predicate-array-diagnostic branch August 18, 2026 23:06
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

objectui: metadata-admin predicate in with a non-literal element silently becomes an empty set — membership false for every row, no diagnostic

2 participants

@os-support-ai@claude
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

fix(app-shell): diagnose non-literal elements in predicate in sets - #5265

Merged
os-support-ai merged 1 commit into
mainfrom
claude/issue-4266-in-predicate-array-diagnostic
Aug 18, 2026
Merged

fix(app-shell): diagnose non-literal elements in predicate in sets#5265
os-support-ai merged 1 commit into
mainfrom
claude/issue-4266-in-predicate-array-diagnostic

Conversation

@os-support-ai

Copy link
Copy Markdown
Collaborator

Fixes#4266

What

predicate.ts's in [...] array branch JSON-parses the bracketed text and, on any parse failure (a non-literal element — a path, a bare identifier, a trailing comma), the catch returned [] with nothing in the console. [].includes(anything) is false, so the predicate silently read FALSE FOR EVERY ROW — and because the parse is whole-set, not per-element, one bad element discarded every good literal sitting next to it too: data.type in ['text', data.a] collapsed exactly as hard as data.type in [data.a] alone.

Fix

Diagnose only, zero semantic change — the ruling this card asked me to measure against #4049's precedent, and matched it: the catch still returns []; an in set that fails to parse is still, and remains, the empty set. A dev-mode console.warn now names the predicate and, best-effort, the element that broke the parse (findUnparseableSetElement, which re-parses each top-level comma-separated element with the same quote-normalising JSON.parse the array branch already uses — for the warning text only, never to change the return value). Falls back to naming the whole set when no single element is individually at fault (e.g. a bare trailing comma). Warn-once keyed on (raw set text, predicate), same discipline as the two existing diagnostics in this file (#6936, #4049).

⛔ Does not widen the declared subset — a path inside in [...] still does not resolve; it is still reported as broken, just no longer silently.

A louder alternative (throw so the whole predicate fails open true, mirroring #6936) was considered and rejected — see the new header section in predicate.ts for the reasoning: false here is the documented behavior for an unparseable set, not a bug the way an unresolved path was, so flipping it to fail-open would be an unruled semantic change.

Premise re-verification

Triage verified on origin/main @ b954120 (a week old). Re-verified on current main @ bc2922a8 (post the two merges from #5227/PR5263 that touched widgets.tsx/loadState.ts in the same directory) — the array branch and its whole-set catch { return []; } were still exactly as described. Also checked whether ROADMAP M9 (real CEL) has landed: @objectstack/formula's cel-engine.ts exists and is already used elsewhere in app-shell (ExpressionProvider.tsx, celAuthoring.ts, clientValidation.ts, …), but SchemaForm.tsx is still the sole consumer of predicate.ts's evaluatePredicate — M9 has not replaced this specific evaluator, so the card is live.

Tests

predicate.test.ts §8 (new): non-literal element fires + names it (bare identifier, path-shaped, amid good literals, trailing-comma fallback), warn-once per (predicate, set) pair, dev-mode-only, and a §8.3 zero-semantics table pinning verdicts identical to the pre-fix [] shape — the same proof-shape as #4049's §7.3. §8.4 pins literal-only in sets completely unaffected (same verdict, silent).

Reverse-verification: restored the pre-fix two-line catch { return []; }, predicted exactly the 6 new assertions that reference the warning would go red (the two toHaveBeenCalledTimes warn-count tests and the four toContain(...) on warning text) while the rest of the file (88 tests, including the new §8.3/§8.4 verdict-only pins) stays green. Observed: exactly those 6 red, 88 green — restored the fix afterward from the committed branch state and re-ran to confirm 94/94 green again.

Gates run locally

  • pnpm --filter '@object-ui/app-shell^...' build (dependency closure) — clean
  • pnpm exec vitest run packages/app-shell/src/views/metadata-admin/predicate.test.ts — 94/94 passed (run from repo root per the package-level-vitest guard in this repo, objectui#3378)
  • pnpm --filter @object-ui/app-shell type-check — clean
  • pnpm --filter @object-ui/app-shell exec eslint src/views/metadata-admin/predicate.ts src/views/metadata-admin/predicate.test.ts — 0 errors (1 pre-existing no-explicit-any warning, unrelated line in resolveValue)
  • node scripts/check-control-bytes.mjs + explicit control-byte grep on both changed files — clean
  • node scripts/check-changeset-presence.mjs — 1 changeset present for the 1 released package touched
  • i18n gates (check:i18n-keys/check:i18n-drift): N/A — this diagnostic is a dev-mode console.warn, same as the two existing diagnostics in this file, neither of which goes through t()/i18n

Final commit: bb75ca165.


Generated by Claude Code

An `in` predicate's array branch JSON-parses the bracketed text and
returns an empty array on any parse failure, with no diagnostic. A
non-literal element (a path, a bare identifier, a trailing comma) collapses
the WHOLE set to [], so membership silently reads false for every row --
even discarding good literal elements sitting next to the bad one.
Diagnose only, mirroring objectui#4049's ruling: zero semantic change. The
catch still returns [], the verdict is untouched; a dev-mode console.warn
now names the predicate and, best-effort, the element that broke the parse.
Fixes#4266
@github-actions

Copy link
Copy Markdown
Contributor

✅ Console Performance Budget

MetricValueBudget
Main entry (gzip)25.3 KB350 KB
Entry fileindex-DGBVb25P.js
StatusPASS

📦 Bundle Size Report

PackageSizeGzipped
app-shell (index.js)9.83KB3.70KB
app-shell (runtime-config.js)7.42KB2.32KB
app-shell (types.js)0.01KB0.04KB
app-shell (urlParams.js)8.92KB3.41KB
auth (AuthContext.js)0.31KB0.24KB
auth (AuthGuard.js)1.17KB0.53KB
auth (AuthProvider.js)29.33KB7.05KB
auth (AuthShell.js)3.49KB1.40KB
auth (ForgotPasswordForm.js)12.21KB3.45KB
auth (LoginForm.js)18.13KB5.39KB
auth (PreviewBanner.js)0.90KB0.50KB
auth (RegisterForm.js)6.64KB2.21KB
auth (SocialSignInButtons.js)9.60KB3.89KB
auth (UserMenu.js)3.40KB1.22KB
auth (auth-gate-events.js)1.29KB0.66KB
auth (authStyles.js)5.04KB1.72KB
auth (createAuthClient.js)40.21KB10.79KB
auth (createAuthenticatedFetch.js)6.34KB2.43KB
auth (index.js)2.71KB1.22KB
auth (invitation-status.js)1.22KB0.70KB
auth (org-roles.js)6.66KB2.78KB
auth (phone-identifier.js)1.11KB0.66KB
auth (types.js)0.59KB0.35KB
auth (useAuth.js)5.02KB0.88KB
auth (useIsWorkspaceAdmin.js)1.61KB0.85KB
collaboration (CommentThread.js)26.07KB7.56KB
collaboration (LiveCursors.js)3.17KB1.27KB
collaboration (PresenceAvatars.js)6.49KB2.64KB
collaboration (PresenceProvider.js)2.79KB1.13KB
collaboration (index.js)1.65KB0.73KB
collaboration (useCollaborationTranslation.js)6.05KB2.52KB
collaboration (useCommentSearch.js)1.98KB0.88KB
collaboration (useConflictResolution.js)7.75KB1.86KB
collaboration (useMentionNotifications.js)1.81KB0.68KB
collaboration (usePresence.js)6.33KB1.84KB
collaboration (useRealtimeSubscription.js)7.91KB2.01KB
components (index.js)506.17KB113.33KB
core (index.js)4.11KB1.62KB
create-plugin (index.js)10.08KB3.26KB
data-objectstack (index.js)159.03KB44.08KB
fields (index.js)237.07KB59.46KB
i18n (LocalizationContext.js)1.76KB0.96KB
i18n (currency.js)1.22KB0.64KB
i18n (i18n.js)4.28KB1.75KB
i18n (index.js)3.42KB1.39KB
i18n (pickLocalized.js)3.69KB1.73KB
i18n (provider.js)23.13KB7.63KB
i18n (useDisplayLocale.js)2.85KB1.45KB
i18n (useObjectLabel.js)29.43KB7.15KB
i18n (useSafeTranslation.js)7.77KB3.13KB
layout (index.js)39.16KB10.97KB
mobile (MobileProvider.js)0.92KB0.49KB
mobile (ResponsiveContainer.js)0.94KB0.38KB
mobile (breakpoints.js)1.51KB0.70KB
mobile (createOfflineDataSource.js)5.61KB1.74KB
mobile (index.js)1.50KB0.62KB
mobile (offlineQueue.js)3.91KB1.35KB
mobile (pwa.js)0.97KB0.49KB
mobile (serviceWorker.js)1.48KB0.62KB
mobile (serviceWorkerSource.js)3.41KB1.48KB
mobile (useBreakpoint.js)1.54KB0.65KB
mobile (useGesture.js)6.96KB1.98KB
mobile (useOfflineSync.js)1.99KB0.72KB
mobile (usePullToRefresh.js)2.53KB0.85KB
mobile (useResponsive.js)0.71KB0.42KB
mobile (useResponsiveConfig.js)1.36KB0.63KB
mobile (useSpecGesture.js)4.32KB1.64KB
mobile (useTouchTarget.js)1.01KB0.54KB
permissions (MePermissionsProvider.js)9.35KB3.31KB
permissions (PermissionContext.js)0.31KB0.25KB
permissions (PermissionGuard.js)0.89KB0.45KB
permissions (PermissionProvider.js)4.42KB1.42KB
permissions (evaluator.js)5.12KB1.74KB
permissions (index.js)0.91KB0.41KB
permissions (store.js)0.91KB0.42KB
permissions (useFieldPermissions.js)1.28KB0.52KB
permissions (usePermissions.js)1.81KB0.83KB
plugin-ai (index.js)15.75KB3.80KB
plugin-calendar (index.js)46.62KB12.83KB
plugin-charts (index.js)64.75KB18.37KB
plugin-chatbot (index.js)181.21KB43.14KB
plugin-dashboard (index.js)128.04KB32.75KB
plugin-designer (index.js)212.39KB42.83KB
plugin-detail (index.js)241.46KB60.56KB
plugin-editor (index.js)2.46KB1.10KB
plugin-form (index.js)123.77KB30.07KB
plugin-gantt (index.js)164.10KB39.87KB
plugin-grid (index.js)198.22KB53.27KB
plugin-kanban (index.js)52.93KB14.60KB
plugin-list (index.js)111.66KB27.13KB
plugin-map (index.js)19.96KB6.56KB
plugin-markdown (index.js)13.72KB4.69KB
plugin-report (index.js)42.84KB11.77KB
plugin-timeline (index.js)26.68KB7.66KB
plugin-tree (index.js)8.50KB2.88KB
plugin-view (index.js)84.08KB20.59KB
providers (DataSourceProvider.js)0.75KB0.39KB
providers (MetadataProvider.js)1.37KB0.59KB
providers (ThemeProvider.js)1.90KB0.85KB
providers (UploadProvider.js)11.66KB3.50KB
providers (index.js)0.44KB0.22KB
providers (types.js)0.01KB0.04KB
react-runtime (index.js)5.62KB2.34KB
react (LazyPluginLoader.js)3.77KB1.33KB
react (SchemaRenderer.js)31.56KB10.70KB
react (data-invalidation.js)5.05KB2.08KB
react (index.js)1.33KB0.69KB
react (schema-input.js)1.45KB0.83KB
react (spec-input.js)0.20KB0.18KB
sdui-parser (codegen.js)5.41KB2.34KB
sdui-parser (index.js)4.77KB2.16KB
sdui-parser (input-type.js)2.84KB1.40KB
sdui-parser (parse.js)10.76KB3.17KB
sdui-parser (provenance.js)3.66KB1.82KB
sdui-parser (types.js)0.29KB0.24KB
sdui-parser (validate.js)6.92KB2.40KB
types (ai.js)0.20KB0.17KB
types (api-types.js)0.20KB0.18KB
types (app.js)2.87KB0.99KB
types (base.js)0.20KB0.18KB
types (blocks.js)0.20KB0.18KB
types (complex.js)0.20KB0.18KB
types (crud.js)0.20KB0.18KB
types (dashboard-filter-alias.js)6.23KB2.74KB
types (data-display.js)0.20KB0.18KB
types (data-protocol.js)0.20KB0.19KB
types (data.js)0.20KB0.18KB
types (designer.js)1.87KB0.85KB
types (disclosure.js)0.20KB0.18KB
types (error-code.js)1.54KB0.88KB
types (feedback.js)0.20KB0.18KB
types (field-types.js)0.20KB0.18KB
types (form.js)0.20KB0.18KB
types (http-retry.js)4.32KB2.02KB
types (index.js)3.08KB1.53KB
types (layout.js)0.20KB0.18KB
types (managed-by.js)0.19KB0.18KB
types (mobile.js)2.59KB1.31KB
types (navigation.js)0.20KB0.18KB
types (objectql.js)0.20KB0.18KB
types (overlay.js)0.20KB0.18KB
types (permissions.js)0.20KB0.18KB
types (plugin-scope.js)0.20KB0.18KB
types (record-components.js)0.20KB0.19KB
types (record-semantics.js)1.28KB0.67KB
types (registry.js)0.20KB0.18KB
types (reports.js)0.20KB0.18KB
types (spec-report.js)5.05KB1.93KB
types (system-fields.js)3.33KB1.54KB
types (theme.js)0.20KB0.18KB
types (ui-action.js)3.40KB1.71KB
types (views.js)0.20KB0.18KB
types (widget.js)0.20KB0.18KB

Size Limits

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

@os-support-ai
os-support-ai marked this pull request as ready for review August 18, 2026 23:05
@os-support-ai
os-support-ai added this pull request to the merge queueAug 18, 2026
Merged via the queue into main with commit 2eb8db8Aug 18, 2026
22 checks passed
@os-support-ai
os-support-ai deleted the claude/issue-4266-in-predicate-array-diagnostic branch August 18, 2026 23:06
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

objectui: metadata-admin predicate in with a non-literal element silently becomes an empty set — membership false for every row, no diagnostic

2 participants

@os-support-ai@claude
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

fix(app-shell): diagnose non-literal elements in predicate in sets - #5265

Merged
os-support-ai merged 1 commit into
mainfrom
claude/issue-4266-in-predicate-array-diagnostic
Aug 18, 2026
Merged

fix(app-shell): diagnose non-literal elements in predicate in sets#5265
os-support-ai merged 1 commit into
mainfrom
claude/issue-4266-in-predicate-array-diagnostic

Conversation

@os-support-ai

Copy link
Copy Markdown
Collaborator

Fixes#4266

What

predicate.ts's in [...] array branch JSON-parses the bracketed text and, on any parse failure (a non-literal element — a path, a bare identifier, a trailing comma), the catch returned [] with nothing in the console. [].includes(anything) is false, so the predicate silently read FALSE FOR EVERY ROW — and because the parse is whole-set, not per-element, one bad element discarded every good literal sitting next to it too: data.type in ['text', data.a] collapsed exactly as hard as data.type in [data.a] alone.

Fix

Diagnose only, zero semantic change — the ruling this card asked me to measure against #4049's precedent, and matched it: the catch still returns []; an in set that fails to parse is still, and remains, the empty set. A dev-mode console.warn now names the predicate and, best-effort, the element that broke the parse (findUnparseableSetElement, which re-parses each top-level comma-separated element with the same quote-normalising JSON.parse the array branch already uses — for the warning text only, never to change the return value). Falls back to naming the whole set when no single element is individually at fault (e.g. a bare trailing comma). Warn-once keyed on (raw set text, predicate), same discipline as the two existing diagnostics in this file (#6936, #4049).

⛔ Does not widen the declared subset — a path inside in [...] still does not resolve; it is still reported as broken, just no longer silently.

A louder alternative (throw so the whole predicate fails open true, mirroring #6936) was considered and rejected — see the new header section in predicate.ts for the reasoning: false here is the documented behavior for an unparseable set, not a bug the way an unresolved path was, so flipping it to fail-open would be an unruled semantic change.

Premise re-verification

Triage verified on origin/main @ b954120 (a week old). Re-verified on current main @ bc2922a8 (post the two merges from #5227/PR5263 that touched widgets.tsx/loadState.ts in the same directory) — the array branch and its whole-set catch { return []; } were still exactly as described. Also checked whether ROADMAP M9 (real CEL) has landed: @objectstack/formula's cel-engine.ts exists and is already used elsewhere in app-shell (ExpressionProvider.tsx, celAuthoring.ts, clientValidation.ts, …), but SchemaForm.tsx is still the sole consumer of predicate.ts's evaluatePredicate — M9 has not replaced this specific evaluator, so the card is live.

Tests

predicate.test.ts §8 (new): non-literal element fires + names it (bare identifier, path-shaped, amid good literals, trailing-comma fallback), warn-once per (predicate, set) pair, dev-mode-only, and a §8.3 zero-semantics table pinning verdicts identical to the pre-fix [] shape — the same proof-shape as #4049's §7.3. §8.4 pins literal-only in sets completely unaffected (same verdict, silent).

Reverse-verification: restored the pre-fix two-line catch { return []; }, predicted exactly the 6 new assertions that reference the warning would go red (the two toHaveBeenCalledTimes warn-count tests and the four toContain(...) on warning text) while the rest of the file (88 tests, including the new §8.3/§8.4 verdict-only pins) stays green. Observed: exactly those 6 red, 88 green — restored the fix afterward from the committed branch state and re-ran to confirm 94/94 green again.

Gates run locally

  • pnpm --filter '@object-ui/app-shell^...' build (dependency closure) — clean
  • pnpm exec vitest run packages/app-shell/src/views/metadata-admin/predicate.test.ts — 94/94 passed (run from repo root per the package-level-vitest guard in this repo, objectui#3378)
  • pnpm --filter @object-ui/app-shell type-check — clean
  • pnpm --filter @object-ui/app-shell exec eslint src/views/metadata-admin/predicate.ts src/views/metadata-admin/predicate.test.ts — 0 errors (1 pre-existing no-explicit-any warning, unrelated line in resolveValue)
  • node scripts/check-control-bytes.mjs + explicit control-byte grep on both changed files — clean
  • node scripts/check-changeset-presence.mjs — 1 changeset present for the 1 released package touched
  • i18n gates (check:i18n-keys/check:i18n-drift): N/A — this diagnostic is a dev-mode console.warn, same as the two existing diagnostics in this file, neither of which goes through t()/i18n

Final commit: bb75ca165.


Generated by Claude Code

An `in` predicate's array branch JSON-parses the bracketed text and
returns an empty array on any parse failure, with no diagnostic. A
non-literal element (a path, a bare identifier, a trailing comma) collapses
the WHOLE set to [], so membership silently reads false for every row --
even discarding good literal elements sitting next to the bad one.
Diagnose only, mirroring objectui#4049's ruling: zero semantic change. The
catch still returns [], the verdict is untouched; a dev-mode console.warn
now names the predicate and, best-effort, the element that broke the parse.
Fixes#4266
@github-actions

Copy link
Copy Markdown
Contributor

✅ Console Performance Budget

MetricValueBudget
Main entry (gzip)25.3 KB350 KB
Entry fileindex-DGBVb25P.js
StatusPASS

📦 Bundle Size Report

PackageSizeGzipped
app-shell (index.js)9.83KB3.70KB
app-shell (runtime-config.js)7.42KB2.32KB
app-shell (types.js)0.01KB0.04KB
app-shell (urlParams.js)8.92KB3.41KB
auth (AuthContext.js)0.31KB0.24KB
auth (AuthGuard.js)1.17KB0.53KB
auth (AuthProvider.js)29.33KB7.05KB
auth (AuthShell.js)3.49KB1.40KB
auth (ForgotPasswordForm.js)12.21KB3.45KB
auth (LoginForm.js)18.13KB5.39KB
auth (PreviewBanner.js)0.90KB0.50KB
auth (RegisterForm.js)6.64KB2.21KB
auth (SocialSignInButtons.js)9.60KB3.89KB
auth (UserMenu.js)3.40KB1.22KB
auth (auth-gate-events.js)1.29KB0.66KB
auth (authStyles.js)5.04KB1.72KB
auth (createAuthClient.js)40.21KB10.79KB
auth (createAuthenticatedFetch.js)6.34KB2.43KB
auth (index.js)2.71KB1.22KB
auth (invitation-status.js)1.22KB0.70KB
auth (org-roles.js)6.66KB2.78KB
auth (phone-identifier.js)1.11KB0.66KB
auth (types.js)0.59KB0.35KB
auth (useAuth.js)5.02KB0.88KB
auth (useIsWorkspaceAdmin.js)1.61KB0.85KB
collaboration (CommentThread.js)26.07KB7.56KB
collaboration (LiveCursors.js)3.17KB1.27KB
collaboration (PresenceAvatars.js)6.49KB2.64KB
collaboration (PresenceProvider.js)2.79KB1.13KB
collaboration (index.js)1.65KB0.73KB
collaboration (useCollaborationTranslation.js)6.05KB2.52KB
collaboration (useCommentSearch.js)1.98KB0.88KB
collaboration (useConflictResolution.js)7.75KB1.86KB
collaboration (useMentionNotifications.js)1.81KB0.68KB
collaboration (usePresence.js)6.33KB1.84KB
collaboration (useRealtimeSubscription.js)7.91KB2.01KB
components (index.js)506.17KB113.33KB
core (index.js)4.11KB1.62KB
create-plugin (index.js)10.08KB3.26KB
data-objectstack (index.js)159.03KB44.08KB
fields (index.js)237.07KB59.46KB
i18n (LocalizationContext.js)1.76KB0.96KB
i18n (currency.js)1.22KB0.64KB
i18n (i18n.js)4.28KB1.75KB
i18n (index.js)3.42KB1.39KB
i18n (pickLocalized.js)3.69KB1.73KB
i18n (provider.js)23.13KB7.63KB
i18n (useDisplayLocale.js)2.85KB1.45KB
i18n (useObjectLabel.js)29.43KB7.15KB
i18n (useSafeTranslation.js)7.77KB3.13KB
layout (index.js)39.16KB10.97KB
mobile (MobileProvider.js)0.92KB0.49KB
mobile (ResponsiveContainer.js)0.94KB0.38KB
mobile (breakpoints.js)1.51KB0.70KB
mobile (createOfflineDataSource.js)5.61KB1.74KB
mobile (index.js)1.50KB0.62KB
mobile (offlineQueue.js)3.91KB1.35KB
mobile (pwa.js)0.97KB0.49KB
mobile (serviceWorker.js)1.48KB0.62KB
mobile (serviceWorkerSource.js)3.41KB1.48KB
mobile (useBreakpoint.js)1.54KB0.65KB
mobile (useGesture.js)6.96KB1.98KB
mobile (useOfflineSync.js)1.99KB0.72KB
mobile (usePullToRefresh.js)2.53KB0.85KB
mobile (useResponsive.js)0.71KB0.42KB
mobile (useResponsiveConfig.js)1.36KB0.63KB
mobile (useSpecGesture.js)4.32KB1.64KB
mobile (useTouchTarget.js)1.01KB0.54KB
permissions (MePermissionsProvider.js)9.35KB3.31KB
permissions (PermissionContext.js)0.31KB0.25KB
permissions (PermissionGuard.js)0.89KB0.45KB
permissions (PermissionProvider.js)4.42KB1.42KB
permissions (evaluator.js)5.12KB1.74KB
permissions (index.js)0.91KB0.41KB
permissions (store.js)0.91KB0.42KB
permissions (useFieldPermissions.js)1.28KB0.52KB
permissions (usePermissions.js)1.81KB0.83KB
plugin-ai (index.js)15.75KB3.80KB
plugin-calendar (index.js)46.62KB12.83KB
plugin-charts (index.js)64.75KB18.37KB
plugin-chatbot (index.js)181.21KB43.14KB
plugin-dashboard (index.js)128.04KB32.75KB
plugin-designer (index.js)212.39KB42.83KB
plugin-detail (index.js)241.46KB60.56KB
plugin-editor (index.js)2.46KB1.10KB
plugin-form (index.js)123.77KB30.07KB
plugin-gantt (index.js)164.10KB39.87KB
plugin-grid (index.js)198.22KB53.27KB
plugin-kanban (index.js)52.93KB14.60KB
plugin-list (index.js)111.66KB27.13KB
plugin-map (index.js)19.96KB6.56KB
plugin-markdown (index.js)13.72KB4.69KB
plugin-report (index.js)42.84KB11.77KB
plugin-timeline (index.js)26.68KB7.66KB
plugin-tree (index.js)8.50KB2.88KB
plugin-view (index.js)84.08KB20.59KB
providers (DataSourceProvider.js)0.75KB0.39KB
providers (MetadataProvider.js)1.37KB0.59KB
providers (ThemeProvider.js)1.90KB0.85KB
providers (UploadProvider.js)11.66KB3.50KB
providers (index.js)0.44KB0.22KB
providers (types.js)0.01KB0.04KB
react-runtime (index.js)5.62KB2.34KB
react (LazyPluginLoader.js)3.77KB1.33KB
react (SchemaRenderer.js)31.56KB10.70KB
react (data-invalidation.js)5.05KB2.08KB
react (index.js)1.33KB0.69KB
react (schema-input.js)1.45KB0.83KB
react (spec-input.js)0.20KB0.18KB
sdui-parser (codegen.js)5.41KB2.34KB
sdui-parser (index.js)4.77KB2.16KB
sdui-parser (input-type.js)2.84KB1.40KB
sdui-parser (parse.js)10.76KB3.17KB
sdui-parser (provenance.js)3.66KB1.82KB
sdui-parser (types.js)0.29KB0.24KB
sdui-parser (validate.js)6.92KB2.40KB
types (ai.js)0.20KB0.17KB
types (api-types.js)0.20KB0.18KB
types (app.js)2.87KB0.99KB
types (base.js)0.20KB0.18KB
types (blocks.js)0.20KB0.18KB
types (complex.js)0.20KB0.18KB
types (crud.js)0.20KB0.18KB
types (dashboard-filter-alias.js)6.23KB2.74KB
types (data-display.js)0.20KB0.18KB
types (data-protocol.js)0.20KB0.19KB
types (data.js)0.20KB0.18KB
types (designer.js)1.87KB0.85KB
types (disclosure.js)0.20KB0.18KB
types (error-code.js)1.54KB0.88KB
types (feedback.js)0.20KB0.18KB
types (field-types.js)0.20KB0.18KB
types (form.js)0.20KB0.18KB
types (http-retry.js)4.32KB2.02KB
types (index.js)3.08KB1.53KB
types (layout.js)0.20KB0.18KB
types (managed-by.js)0.19KB0.18KB
types (mobile.js)2.59KB1.31KB
types (navigation.js)0.20KB0.18KB
types (objectql.js)0.20KB0.18KB
types (overlay.js)0.20KB0.18KB
types (permissions.js)0.20KB0.18KB
types (plugin-scope.js)0.20KB0.18KB
types (record-components.js)0.20KB0.19KB
types (record-semantics.js)1.28KB0.67KB
types (registry.js)0.20KB0.18KB
types (reports.js)0.20KB0.18KB
types (spec-report.js)5.05KB1.93KB
types (system-fields.js)3.33KB1.54KB
types (theme.js)0.20KB0.18KB
types (ui-action.js)3.40KB1.71KB
types (views.js)0.20KB0.18KB
types (widget.js)0.20KB0.18KB

Size Limits

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

@os-support-ai
os-support-ai marked this pull request as ready for review August 18, 2026 23:05
@os-support-ai
os-support-ai added this pull request to the merge queueAug 18, 2026
Merged via the queue into main with commit 2eb8db8Aug 18, 2026
22 checks passed
@os-support-ai
os-support-ai deleted the claude/issue-4266-in-predicate-array-diagnostic branch August 18, 2026 23:06
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

objectui: metadata-admin predicate in with a non-literal element silently becomes an empty set — membership false for every row, no diagnostic

2 participants

@os-support-ai@claude
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

fix(app-shell): diagnose non-literal elements in predicate in sets - #5265

Merged
os-support-ai merged 1 commit into
mainfrom
claude/issue-4266-in-predicate-array-diagnostic
Aug 18, 2026
Merged

fix(app-shell): diagnose non-literal elements in predicate in sets#5265
os-support-ai merged 1 commit into
mainfrom
claude/issue-4266-in-predicate-array-diagnostic

Conversation

@os-support-ai

Copy link
Copy Markdown
Collaborator

Fixes#4266

What

predicate.ts's in [...] array branch JSON-parses the bracketed text and, on any parse failure (a non-literal element — a path, a bare identifier, a trailing comma), the catch returned [] with nothing in the console. [].includes(anything) is false, so the predicate silently read FALSE FOR EVERY ROW — and because the parse is whole-set, not per-element, one bad element discarded every good literal sitting next to it too: data.type in ['text', data.a] collapsed exactly as hard as data.type in [data.a] alone.

Fix

Diagnose only, zero semantic change — the ruling this card asked me to measure against #4049's precedent, and matched it: the catch still returns []; an in set that fails to parse is still, and remains, the empty set. A dev-mode console.warn now names the predicate and, best-effort, the element that broke the parse (findUnparseableSetElement, which re-parses each top-level comma-separated element with the same quote-normalising JSON.parse the array branch already uses — for the warning text only, never to change the return value). Falls back to naming the whole set when no single element is individually at fault (e.g. a bare trailing comma). Warn-once keyed on (raw set text, predicate), same discipline as the two existing diagnostics in this file (#6936, #4049).

⛔ Does not widen the declared subset — a path inside in [...] still does not resolve; it is still reported as broken, just no longer silently.

A louder alternative (throw so the whole predicate fails open true, mirroring #6936) was considered and rejected — see the new header section in predicate.ts for the reasoning: false here is the documented behavior for an unparseable set, not a bug the way an unresolved path was, so flipping it to fail-open would be an unruled semantic change.

Premise re-verification

Triage verified on origin/main @ b954120 (a week old). Re-verified on current main @ bc2922a8 (post the two merges from #5227/PR5263 that touched widgets.tsx/loadState.ts in the same directory) — the array branch and its whole-set catch { return []; } were still exactly as described. Also checked whether ROADMAP M9 (real CEL) has landed: @objectstack/formula's cel-engine.ts exists and is already used elsewhere in app-shell (ExpressionProvider.tsx, celAuthoring.ts, clientValidation.ts, …), but SchemaForm.tsx is still the sole consumer of predicate.ts's evaluatePredicate — M9 has not replaced this specific evaluator, so the card is live.

Tests

predicate.test.ts §8 (new): non-literal element fires + names it (bare identifier, path-shaped, amid good literals, trailing-comma fallback), warn-once per (predicate, set) pair, dev-mode-only, and a §8.3 zero-semantics table pinning verdicts identical to the pre-fix [] shape — the same proof-shape as #4049's §7.3. §8.4 pins literal-only in sets completely unaffected (same verdict, silent).

Reverse-verification: restored the pre-fix two-line catch { return []; }, predicted exactly the 6 new assertions that reference the warning would go red (the two toHaveBeenCalledTimes warn-count tests and the four toContain(...) on warning text) while the rest of the file (88 tests, including the new §8.3/§8.4 verdict-only pins) stays green. Observed: exactly those 6 red, 88 green — restored the fix afterward from the committed branch state and re-ran to confirm 94/94 green again.

Gates run locally

  • pnpm --filter '@object-ui/app-shell^...' build (dependency closure) — clean
  • pnpm exec vitest run packages/app-shell/src/views/metadata-admin/predicate.test.ts — 94/94 passed (run from repo root per the package-level-vitest guard in this repo, objectui#3378)
  • pnpm --filter @object-ui/app-shell type-check — clean
  • pnpm --filter @object-ui/app-shell exec eslint src/views/metadata-admin/predicate.ts src/views/metadata-admin/predicate.test.ts — 0 errors (1 pre-existing no-explicit-any warning, unrelated line in resolveValue)
  • node scripts/check-control-bytes.mjs + explicit control-byte grep on both changed files — clean
  • node scripts/check-changeset-presence.mjs — 1 changeset present for the 1 released package touched
  • i18n gates (check:i18n-keys/check:i18n-drift): N/A — this diagnostic is a dev-mode console.warn, same as the two existing diagnostics in this file, neither of which goes through t()/i18n

Final commit: bb75ca165.


Generated by Claude Code

An `in` predicate's array branch JSON-parses the bracketed text and
returns an empty array on any parse failure, with no diagnostic. A
non-literal element (a path, a bare identifier, a trailing comma) collapses
the WHOLE set to [], so membership silently reads false for every row --
even discarding good literal elements sitting next to the bad one.
Diagnose only, mirroring objectui#4049's ruling: zero semantic change. The
catch still returns [], the verdict is untouched; a dev-mode console.warn
now names the predicate and, best-effort, the element that broke the parse.
Fixes#4266
@github-actions

Copy link
Copy Markdown
Contributor

✅ Console Performance Budget

MetricValueBudget
Main entry (gzip)25.3 KB350 KB
Entry fileindex-DGBVb25P.js
StatusPASS

📦 Bundle Size Report

PackageSizeGzipped
app-shell (index.js)9.83KB3.70KB
app-shell (runtime-config.js)7.42KB2.32KB
app-shell (types.js)0.01KB0.04KB
app-shell (urlParams.js)8.92KB3.41KB
auth (AuthContext.js)0.31KB0.24KB
auth (AuthGuard.js)1.17KB0.53KB
auth (AuthProvider.js)29.33KB7.05KB
auth (AuthShell.js)3.49KB1.40KB
auth (ForgotPasswordForm.js)12.21KB3.45KB
auth (LoginForm.js)18.13KB5.39KB
auth (PreviewBanner.js)0.90KB0.50KB
auth (RegisterForm.js)6.64KB2.21KB
auth (SocialSignInButtons.js)9.60KB3.89KB
auth (UserMenu.js)3.40KB1.22KB
auth (auth-gate-events.js)1.29KB0.66KB
auth (authStyles.js)5.04KB1.72KB
auth (createAuthClient.js)40.21KB10.79KB
auth (createAuthenticatedFetch.js)6.34KB2.43KB
auth (index.js)2.71KB1.22KB
auth (invitation-status.js)1.22KB0.70KB
auth (org-roles.js)6.66KB2.78KB
auth (phone-identifier.js)1.11KB0.66KB
auth (types.js)0.59KB0.35KB
auth (useAuth.js)5.02KB0.88KB
auth (useIsWorkspaceAdmin.js)1.61KB0.85KB
collaboration (CommentThread.js)26.07KB7.56KB
collaboration (LiveCursors.js)3.17KB1.27KB
collaboration (PresenceAvatars.js)6.49KB2.64KB
collaboration (PresenceProvider.js)2.79KB1.13KB
collaboration (index.js)1.65KB0.73KB
collaboration (useCollaborationTranslation.js)6.05KB2.52KB
collaboration (useCommentSearch.js)1.98KB0.88KB
collaboration (useConflictResolution.js)7.75KB1.86KB
collaboration (useMentionNotifications.js)1.81KB0.68KB
collaboration (usePresence.js)6.33KB1.84KB
collaboration (useRealtimeSubscription.js)7.91KB2.01KB
components (index.js)506.17KB113.33KB
core (index.js)4.11KB1.62KB
create-plugin (index.js)10.08KB3.26KB
data-objectstack (index.js)159.03KB44.08KB
fields (index.js)237.07KB59.46KB
i18n (LocalizationContext.js)1.76KB0.96KB
i18n (currency.js)1.22KB0.64KB
i18n (i18n.js)4.28KB1.75KB
i18n (index.js)3.42KB1.39KB
i18n (pickLocalized.js)3.69KB1.73KB
i18n (provider.js)23.13KB7.63KB
i18n (useDisplayLocale.js)2.85KB1.45KB
i18n (useObjectLabel.js)29.43KB7.15KB
i18n (useSafeTranslation.js)7.77KB3.13KB
layout (index.js)39.16KB10.97KB
mobile (MobileProvider.js)0.92KB0.49KB
mobile (ResponsiveContainer.js)0.94KB0.38KB
mobile (breakpoints.js)1.51KB0.70KB
mobile (createOfflineDataSource.js)5.61KB1.74KB
mobile (index.js)1.50KB0.62KB
mobile (offlineQueue.js)3.91KB1.35KB
mobile (pwa.js)0.97KB0.49KB
mobile (serviceWorker.js)1.48KB0.62KB
mobile (serviceWorkerSource.js)3.41KB1.48KB
mobile (useBreakpoint.js)1.54KB0.65KB
mobile (useGesture.js)6.96KB1.98KB
mobile (useOfflineSync.js)1.99KB0.72KB
mobile (usePullToRefresh.js)2.53KB0.85KB
mobile (useResponsive.js)0.71KB0.42KB
mobile (useResponsiveConfig.js)1.36KB0.63KB
mobile (useSpecGesture.js)4.32KB1.64KB
mobile (useTouchTarget.js)1.01KB0.54KB
permissions (MePermissionsProvider.js)9.35KB3.31KB
permissions (PermissionContext.js)0.31KB0.25KB
permissions (PermissionGuard.js)0.89KB0.45KB
permissions (PermissionProvider.js)4.42KB1.42KB
permissions (evaluator.js)5.12KB1.74KB
permissions (index.js)0.91KB0.41KB
permissions (store.js)0.91KB0.42KB
permissions (useFieldPermissions.js)1.28KB0.52KB
permissions (usePermissions.js)1.81KB0.83KB
plugin-ai (index.js)15.75KB3.80KB
plugin-calendar (index.js)46.62KB12.83KB
plugin-charts (index.js)64.75KB18.37KB
plugin-chatbot (index.js)181.21KB43.14KB
plugin-dashboard (index.js)128.04KB32.75KB
plugin-designer (index.js)212.39KB42.83KB
plugin-detail (index.js)241.46KB60.56KB
plugin-editor (index.js)2.46KB1.10KB
plugin-form (index.js)123.77KB30.07KB
plugin-gantt (index.js)164.10KB39.87KB
plugin-grid (index.js)198.22KB53.27KB
plugin-kanban (index.js)52.93KB14.60KB
plugin-list (index.js)111.66KB27.13KB
plugin-map (index.js)19.96KB6.56KB
plugin-markdown (index.js)13.72KB4.69KB
plugin-report (index.js)42.84KB11.77KB
plugin-timeline (index.js)26.68KB7.66KB
plugin-tree (index.js)8.50KB2.88KB
plugin-view (index.js)84.08KB20.59KB
providers (DataSourceProvider.js)0.75KB0.39KB
providers (MetadataProvider.js)1.37KB0.59KB
providers (ThemeProvider.js)1.90KB0.85KB
providers (UploadProvider.js)11.66KB3.50KB
providers (index.js)0.44KB0.22KB
providers (types.js)0.01KB0.04KB
react-runtime (index.js)5.62KB2.34KB
react (LazyPluginLoader.js)3.77KB1.33KB
react (SchemaRenderer.js)31.56KB10.70KB
react (data-invalidation.js)5.05KB2.08KB
react (index.js)1.33KB0.69KB
react (schema-input.js)1.45KB0.83KB
react (spec-input.js)0.20KB0.18KB
sdui-parser (codegen.js)5.41KB2.34KB
sdui-parser (index.js)4.77KB2.16KB
sdui-parser (input-type.js)2.84KB1.40KB
sdui-parser (parse.js)10.76KB3.17KB
sdui-parser (provenance.js)3.66KB1.82KB
sdui-parser (types.js)0.29KB0.24KB
sdui-parser (validate.js)6.92KB2.40KB
types (ai.js)0.20KB0.17KB
types (api-types.js)0.20KB0.18KB
types (app.js)2.87KB0.99KB
types (base.js)0.20KB0.18KB
types (blocks.js)0.20KB0.18KB
types (complex.js)0.20KB0.18KB
types (crud.js)0.20KB0.18KB
types (dashboard-filter-alias.js)6.23KB2.74KB
types (data-display.js)0.20KB0.18KB
types (data-protocol.js)0.20KB0.19KB
types (data.js)0.20KB0.18KB
types (designer.js)1.87KB0.85KB
types (disclosure.js)0.20KB0.18KB
types (error-code.js)1.54KB0.88KB
types (feedback.js)0.20KB0.18KB
types (field-types.js)0.20KB0.18KB
types (form.js)0.20KB0.18KB
types (http-retry.js)4.32KB2.02KB
types (index.js)3.08KB1.53KB
types (layout.js)0.20KB0.18KB
types (managed-by.js)0.19KB0.18KB
types (mobile.js)2.59KB1.31KB
types (navigation.js)0.20KB0.18KB
types (objectql.js)0.20KB0.18KB
types (overlay.js)0.20KB0.18KB
types (permissions.js)0.20KB0.18KB
types (plugin-scope.js)0.20KB0.18KB
types (record-components.js)0.20KB0.19KB
types (record-semantics.js)1.28KB0.67KB
types (registry.js)0.20KB0.18KB
types (reports.js)0.20KB0.18KB
types (spec-report.js)5.05KB1.93KB
types (system-fields.js)3.33KB1.54KB
types (theme.js)0.20KB0.18KB
types (ui-action.js)3.40KB1.71KB
types (views.js)0.20KB0.18KB
types (widget.js)0.20KB0.18KB

Size Limits

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

@os-support-ai
os-support-ai marked this pull request as ready for review August 18, 2026 23:05
@os-support-ai
os-support-ai added this pull request to the merge queueAug 18, 2026
Merged via the queue into main with commit 2eb8db8Aug 18, 2026
22 checks passed
@os-support-ai
os-support-ai deleted the claude/issue-4266-in-predicate-array-diagnostic branch August 18, 2026 23:06
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

objectui: metadata-admin predicate in with a non-literal element silently becomes an empty set — membership false for every row, no diagnostic

2 participants

@os-support-ai@claude
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

fix(app-shell): diagnose non-literal elements in predicate in sets - #5265

Merged
os-support-ai merged 1 commit into
mainfrom
claude/issue-4266-in-predicate-array-diagnostic
Aug 18, 2026
Merged

fix(app-shell): diagnose non-literal elements in predicate in sets#5265
os-support-ai merged 1 commit into
mainfrom
claude/issue-4266-in-predicate-array-diagnostic

Conversation

@os-support-ai

Copy link
Copy Markdown
Collaborator

Fixes#4266

What

predicate.ts's in [...] array branch JSON-parses the bracketed text and, on any parse failure (a non-literal element — a path, a bare identifier, a trailing comma), the catch returned [] with nothing in the console. [].includes(anything) is false, so the predicate silently read FALSE FOR EVERY ROW — and because the parse is whole-set, not per-element, one bad element discarded every good literal sitting next to it too: data.type in ['text', data.a] collapsed exactly as hard as data.type in [data.a] alone.

Fix

Diagnose only, zero semantic change — the ruling this card asked me to measure against #4049's precedent, and matched it: the catch still returns []; an in set that fails to parse is still, and remains, the empty set. A dev-mode console.warn now names the predicate and, best-effort, the element that broke the parse (findUnparseableSetElement, which re-parses each top-level comma-separated element with the same quote-normalising JSON.parse the array branch already uses — for the warning text only, never to change the return value). Falls back to naming the whole set when no single element is individually at fault (e.g. a bare trailing comma). Warn-once keyed on (raw set text, predicate), same discipline as the two existing diagnostics in this file (#6936, #4049).

⛔ Does not widen the declared subset — a path inside in [...] still does not resolve; it is still reported as broken, just no longer silently.

A louder alternative (throw so the whole predicate fails open true, mirroring #6936) was considered and rejected — see the new header section in predicate.ts for the reasoning: false here is the documented behavior for an unparseable set, not a bug the way an unresolved path was, so flipping it to fail-open would be an unruled semantic change.

Premise re-verification

Triage verified on origin/main @ b954120 (a week old). Re-verified on current main @ bc2922a8 (post the two merges from #5227/PR5263 that touched widgets.tsx/loadState.ts in the same directory) — the array branch and its whole-set catch { return []; } were still exactly as described. Also checked whether ROADMAP M9 (real CEL) has landed: @objectstack/formula's cel-engine.ts exists and is already used elsewhere in app-shell (ExpressionProvider.tsx, celAuthoring.ts, clientValidation.ts, …), but SchemaForm.tsx is still the sole consumer of predicate.ts's evaluatePredicate — M9 has not replaced this specific evaluator, so the card is live.

Tests

predicate.test.ts §8 (new): non-literal element fires + names it (bare identifier, path-shaped, amid good literals, trailing-comma fallback), warn-once per (predicate, set) pair, dev-mode-only, and a §8.3 zero-semantics table pinning verdicts identical to the pre-fix [] shape — the same proof-shape as #4049's §7.3. §8.4 pins literal-only in sets completely unaffected (same verdict, silent).

Reverse-verification: restored the pre-fix two-line catch { return []; }, predicted exactly the 6 new assertions that reference the warning would go red (the two toHaveBeenCalledTimes warn-count tests and the four toContain(...) on warning text) while the rest of the file (88 tests, including the new §8.3/§8.4 verdict-only pins) stays green. Observed: exactly those 6 red, 88 green — restored the fix afterward from the committed branch state and re-ran to confirm 94/94 green again.

Gates run locally

  • pnpm --filter '@object-ui/app-shell^...' build (dependency closure) — clean
  • pnpm exec vitest run packages/app-shell/src/views/metadata-admin/predicate.test.ts — 94/94 passed (run from repo root per the package-level-vitest guard in this repo, objectui#3378)
  • pnpm --filter @object-ui/app-shell type-check — clean
  • pnpm --filter @object-ui/app-shell exec eslint src/views/metadata-admin/predicate.ts src/views/metadata-admin/predicate.test.ts — 0 errors (1 pre-existing no-explicit-any warning, unrelated line in resolveValue)
  • node scripts/check-control-bytes.mjs + explicit control-byte grep on both changed files — clean
  • node scripts/check-changeset-presence.mjs — 1 changeset present for the 1 released package touched
  • i18n gates (check:i18n-keys/check:i18n-drift): N/A — this diagnostic is a dev-mode console.warn, same as the two existing diagnostics in this file, neither of which goes through t()/i18n

Final commit: bb75ca165.


Generated by Claude Code

An `in` predicate's array branch JSON-parses the bracketed text and
returns an empty array on any parse failure, with no diagnostic. A
non-literal element (a path, a bare identifier, a trailing comma) collapses
the WHOLE set to [], so membership silently reads false for every row --
even discarding good literal elements sitting next to the bad one.
Diagnose only, mirroring objectui#4049's ruling: zero semantic change. The
catch still returns [], the verdict is untouched; a dev-mode console.warn
now names the predicate and, best-effort, the element that broke the parse.
Fixes#4266
@github-actions

Copy link
Copy Markdown
Contributor

✅ Console Performance Budget

MetricValueBudget
Main entry (gzip)25.3 KB350 KB
Entry fileindex-DGBVb25P.js
StatusPASS

📦 Bundle Size Report

PackageSizeGzipped
app-shell (index.js)9.83KB3.70KB
app-shell (runtime-config.js)7.42KB2.32KB
app-shell (types.js)0.01KB0.04KB
app-shell (urlParams.js)8.92KB3.41KB
auth (AuthContext.js)0.31KB0.24KB
auth (AuthGuard.js)1.17KB0.53KB
auth (AuthProvider.js)29.33KB7.05KB
auth (AuthShell.js)3.49KB1.40KB
auth (ForgotPasswordForm.js)12.21KB3.45KB
auth (LoginForm.js)18.13KB5.39KB
auth (PreviewBanner.js)0.90KB0.50KB
auth (RegisterForm.js)6.64KB2.21KB
auth (SocialSignInButtons.js)9.60KB3.89KB
auth (UserMenu.js)3.40KB1.22KB
auth (auth-gate-events.js)1.29KB0.66KB
auth (authStyles.js)5.04KB1.72KB
auth (createAuthClient.js)40.21KB10.79KB
auth (createAuthenticatedFetch.js)6.34KB2.43KB
auth (index.js)2.71KB1.22KB
auth (invitation-status.js)1.22KB0.70KB
auth (org-roles.js)6.66KB2.78KB
auth (phone-identifier.js)1.11KB0.66KB
auth (types.js)0.59KB0.35KB
auth (useAuth.js)5.02KB0.88KB
auth (useIsWorkspaceAdmin.js)1.61KB0.85KB
collaboration (CommentThread.js)26.07KB7.56KB
collaboration (LiveCursors.js)3.17KB1.27KB
collaboration (PresenceAvatars.js)6.49KB2.64KB
collaboration (PresenceProvider.js)2.79KB1.13KB
collaboration (index.js)1.65KB0.73KB
collaboration (useCollaborationTranslation.js)6.05KB2.52KB
collaboration (useCommentSearch.js)1.98KB0.88KB
collaboration (useConflictResolution.js)7.75KB1.86KB
collaboration (useMentionNotifications.js)1.81KB0.68KB
collaboration (usePresence.js)6.33KB1.84KB
collaboration (useRealtimeSubscription.js)7.91KB2.01KB
components (index.js)506.17KB113.33KB
core (index.js)4.11KB1.62KB
create-plugin (index.js)10.08KB3.26KB
data-objectstack (index.js)159.03KB44.08KB
fields (index.js)237.07KB59.46KB
i18n (LocalizationContext.js)1.76KB0.96KB
i18n (currency.js)1.22KB0.64KB
i18n (i18n.js)4.28KB1.75KB
i18n (index.js)3.42KB1.39KB
i18n (pickLocalized.js)3.69KB1.73KB
i18n (provider.js)23.13KB7.63KB
i18n (useDisplayLocale.js)2.85KB1.45KB
i18n (useObjectLabel.js)29.43KB7.15KB
i18n (useSafeTranslation.js)7.77KB3.13KB
layout (index.js)39.16KB10.97KB
mobile (MobileProvider.js)0.92KB0.49KB
mobile (ResponsiveContainer.js)0.94KB0.38KB
mobile (breakpoints.js)1.51KB0.70KB
mobile (createOfflineDataSource.js)5.61KB1.74KB
mobile (index.js)1.50KB0.62KB
mobile (offlineQueue.js)3.91KB1.35KB
mobile (pwa.js)0.97KB0.49KB
mobile (serviceWorker.js)1.48KB0.62KB
mobile (serviceWorkerSource.js)3.41KB1.48KB
mobile (useBreakpoint.js)1.54KB0.65KB
mobile (useGesture.js)6.96KB1.98KB
mobile (useOfflineSync.js)1.99KB0.72KB
mobile (usePullToRefresh.js)2.53KB0.85KB
mobile (useResponsive.js)0.71KB0.42KB
mobile (useResponsiveConfig.js)1.36KB0.63KB
mobile (useSpecGesture.js)4.32KB1.64KB
mobile (useTouchTarget.js)1.01KB0.54KB
permissions (MePermissionsProvider.js)9.35KB3.31KB
permissions (PermissionContext.js)0.31KB0.25KB
permissions (PermissionGuard.js)0.89KB0.45KB
permissions (PermissionProvider.js)4.42KB1.42KB
permissions (evaluator.js)5.12KB1.74KB
permissions (index.js)0.91KB0.41KB
permissions (store.js)0.91KB0.42KB
permissions (useFieldPermissions.js)1.28KB0.52KB
permissions (usePermissions.js)1.81KB0.83KB
plugin-ai (index.js)15.75KB3.80KB
plugin-calendar (index.js)46.62KB12.83KB
plugin-charts (index.js)64.75KB18.37KB
plugin-chatbot (index.js)181.21KB43.14KB
plugin-dashboard (index.js)128.04KB32.75KB
plugin-designer (index.js)212.39KB42.83KB
plugin-detail (index.js)241.46KB60.56KB
plugin-editor (index.js)2.46KB1.10KB
plugin-form (index.js)123.77KB30.07KB
plugin-gantt (index.js)164.10KB39.87KB
plugin-grid (index.js)198.22KB53.27KB
plugin-kanban (index.js)52.93KB14.60KB
plugin-list (index.js)111.66KB27.13KB
plugin-map (index.js)19.96KB6.56KB
plugin-markdown (index.js)13.72KB4.69KB
plugin-report (index.js)42.84KB11.77KB
plugin-timeline (index.js)26.68KB7.66KB
plugin-tree (index.js)8.50KB2.88KB
plugin-view (index.js)84.08KB20.59KB
providers (DataSourceProvider.js)0.75KB0.39KB
providers (MetadataProvider.js)1.37KB0.59KB
providers (ThemeProvider.js)1.90KB0.85KB
providers (UploadProvider.js)11.66KB3.50KB
providers (index.js)0.44KB0.22KB
providers (types.js)0.01KB0.04KB
react-runtime (index.js)5.62KB2.34KB
react (LazyPluginLoader.js)3.77KB1.33KB
react (SchemaRenderer.js)31.56KB10.70KB
react (data-invalidation.js)5.05KB2.08KB
react (index.js)1.33KB0.69KB
react (schema-input.js)1.45KB0.83KB
react (spec-input.js)0.20KB0.18KB
sdui-parser (codegen.js)5.41KB2.34KB
sdui-parser (index.js)4.77KB2.16KB
sdui-parser (input-type.js)2.84KB1.40KB
sdui-parser (parse.js)10.76KB3.17KB
sdui-parser (provenance.js)3.66KB1.82KB
sdui-parser (types.js)0.29KB0.24KB
sdui-parser (validate.js)6.92KB2.40KB
types (ai.js)0.20KB0.17KB
types (api-types.js)0.20KB0.18KB
types (app.js)2.87KB0.99KB
types (base.js)0.20KB0.18KB
types (blocks.js)0.20KB0.18KB
types (complex.js)0.20KB0.18KB
types (crud.js)0.20KB0.18KB
types (dashboard-filter-alias.js)6.23KB2.74KB
types (data-display.js)0.20KB0.18KB
types (data-protocol.js)0.20KB0.19KB
types (data.js)0.20KB0.18KB
types (designer.js)1.87KB0.85KB
types (disclosure.js)0.20KB0.18KB
types (error-code.js)1.54KB0.88KB
types (feedback.js)0.20KB0.18KB
types (field-types.js)0.20KB0.18KB
types (form.js)0.20KB0.18KB
types (http-retry.js)4.32KB2.02KB
types (index.js)3.08KB1.53KB
types (layout.js)0.20KB0.18KB
types (managed-by.js)0.19KB0.18KB
types (mobile.js)2.59KB1.31KB
types (navigation.js)0.20KB0.18KB
types (objectql.js)0.20KB0.18KB
types (overlay.js)0.20KB0.18KB
types (permissions.js)0.20KB0.18KB
types (plugin-scope.js)0.20KB0.18KB
types (record-components.js)0.20KB0.19KB
types (record-semantics.js)1.28KB0.67KB
types (registry.js)0.20KB0.18KB
types (reports.js)0.20KB0.18KB
types (spec-report.js)5.05KB1.93KB
types (system-fields.js)3.33KB1.54KB
types (theme.js)0.20KB0.18KB
types (ui-action.js)3.40KB1.71KB
types (views.js)0.20KB0.18KB
types (widget.js)0.20KB0.18KB

Size Limits

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

@os-support-ai
os-support-ai marked this pull request as ready for review August 18, 2026 23:05
@os-support-ai
os-support-ai added this pull request to the merge queueAug 18, 2026
Merged via the queue into main with commit 2eb8db8Aug 18, 2026
22 checks passed
@os-support-ai
os-support-ai deleted the claude/issue-4266-in-predicate-array-diagnostic branch August 18, 2026 23:06
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

objectui: metadata-admin predicate in with a non-literal element silently becomes an empty set — membership false for every row, no diagnostic

2 participants

@os-support-ai@claude
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

fix(app-shell): diagnose non-literal elements in predicate in sets - #5265

Merged
os-support-ai merged 1 commit into
mainfrom
claude/issue-4266-in-predicate-array-diagnostic
Aug 18, 2026
Merged

fix(app-shell): diagnose non-literal elements in predicate in sets#5265
os-support-ai merged 1 commit into
mainfrom
claude/issue-4266-in-predicate-array-diagnostic

Conversation

@os-support-ai

Copy link
Copy Markdown
Collaborator

Fixes#4266

What

predicate.ts's in [...] array branch JSON-parses the bracketed text and, on any parse failure (a non-literal element — a path, a bare identifier, a trailing comma), the catch returned [] with nothing in the console. [].includes(anything) is false, so the predicate silently read FALSE FOR EVERY ROW — and because the parse is whole-set, not per-element, one bad element discarded every good literal sitting next to it too: data.type in ['text', data.a] collapsed exactly as hard as data.type in [data.a] alone.

Fix

Diagnose only, zero semantic change — the ruling this card asked me to measure against #4049's precedent, and matched it: the catch still returns []; an in set that fails to parse is still, and remains, the empty set. A dev-mode console.warn now names the predicate and, best-effort, the element that broke the parse (findUnparseableSetElement, which re-parses each top-level comma-separated element with the same quote-normalising JSON.parse the array branch already uses — for the warning text only, never to change the return value). Falls back to naming the whole set when no single element is individually at fault (e.g. a bare trailing comma). Warn-once keyed on (raw set text, predicate), same discipline as the two existing diagnostics in this file (#6936, #4049).

⛔ Does not widen the declared subset — a path inside in [...] still does not resolve; it is still reported as broken, just no longer silently.

A louder alternative (throw so the whole predicate fails open true, mirroring #6936) was considered and rejected — see the new header section in predicate.ts for the reasoning: false here is the documented behavior for an unparseable set, not a bug the way an unresolved path was, so flipping it to fail-open would be an unruled semantic change.

Premise re-verification

Triage verified on origin/main @ b954120 (a week old). Re-verified on current main @ bc2922a8 (post the two merges from #5227/PR5263 that touched widgets.tsx/loadState.ts in the same directory) — the array branch and its whole-set catch { return []; } were still exactly as described. Also checked whether ROADMAP M9 (real CEL) has landed: @objectstack/formula's cel-engine.ts exists and is already used elsewhere in app-shell (ExpressionProvider.tsx, celAuthoring.ts, clientValidation.ts, …), but SchemaForm.tsx is still the sole consumer of predicate.ts's evaluatePredicate — M9 has not replaced this specific evaluator, so the card is live.

Tests

predicate.test.ts §8 (new): non-literal element fires + names it (bare identifier, path-shaped, amid good literals, trailing-comma fallback), warn-once per (predicate, set) pair, dev-mode-only, and a §8.3 zero-semantics table pinning verdicts identical to the pre-fix [] shape — the same proof-shape as #4049's §7.3. §8.4 pins literal-only in sets completely unaffected (same verdict, silent).

Reverse-verification: restored the pre-fix two-line catch { return []; }, predicted exactly the 6 new assertions that reference the warning would go red (the two toHaveBeenCalledTimes warn-count tests and the four toContain(...) on warning text) while the rest of the file (88 tests, including the new §8.3/§8.4 verdict-only pins) stays green. Observed: exactly those 6 red, 88 green — restored the fix afterward from the committed branch state and re-ran to confirm 94/94 green again.

Gates run locally

  • pnpm --filter '@object-ui/app-shell^...' build (dependency closure) — clean
  • pnpm exec vitest run packages/app-shell/src/views/metadata-admin/predicate.test.ts — 94/94 passed (run from repo root per the package-level-vitest guard in this repo, objectui#3378)
  • pnpm --filter @object-ui/app-shell type-check — clean
  • pnpm --filter @object-ui/app-shell exec eslint src/views/metadata-admin/predicate.ts src/views/metadata-admin/predicate.test.ts — 0 errors (1 pre-existing no-explicit-any warning, unrelated line in resolveValue)
  • node scripts/check-control-bytes.mjs + explicit control-byte grep on both changed files — clean
  • node scripts/check-changeset-presence.mjs — 1 changeset present for the 1 released package touched
  • i18n gates (check:i18n-keys/check:i18n-drift): N/A — this diagnostic is a dev-mode console.warn, same as the two existing diagnostics in this file, neither of which goes through t()/i18n

Final commit: bb75ca165.


Generated by Claude Code

An `in` predicate's array branch JSON-parses the bracketed text and
returns an empty array on any parse failure, with no diagnostic. A
non-literal element (a path, a bare identifier, a trailing comma) collapses
the WHOLE set to [], so membership silently reads false for every row --
even discarding good literal elements sitting next to the bad one.
Diagnose only, mirroring objectui#4049's ruling: zero semantic change. The
catch still returns [], the verdict is untouched; a dev-mode console.warn
now names the predicate and, best-effort, the element that broke the parse.
Fixes#4266
@github-actions

Copy link
Copy Markdown
Contributor

✅ Console Performance Budget

MetricValueBudget
Main entry (gzip)25.3 KB350 KB
Entry fileindex-DGBVb25P.js
StatusPASS

📦 Bundle Size Report

PackageSizeGzipped
app-shell (index.js)9.83KB3.70KB
app-shell (runtime-config.js)7.42KB2.32KB
app-shell (types.js)0.01KB0.04KB
app-shell (urlParams.js)8.92KB3.41KB
auth (AuthContext.js)0.31KB0.24KB
auth (AuthGuard.js)1.17KB0.53KB
auth (AuthProvider.js)29.33KB7.05KB
auth (AuthShell.js)3.49KB1.40KB
auth (ForgotPasswordForm.js)12.21KB3.45KB
auth (LoginForm.js)18.13KB5.39KB
auth (PreviewBanner.js)0.90KB0.50KB
auth (RegisterForm.js)6.64KB2.21KB
auth (SocialSignInButtons.js)9.60KB3.89KB
auth (UserMenu.js)3.40KB1.22KB
auth (auth-gate-events.js)1.29KB0.66KB
auth (authStyles.js)5.04KB1.72KB
auth (createAuthClient.js)40.21KB10.79KB
auth (createAuthenticatedFetch.js)6.34KB2.43KB
auth (index.js)2.71KB1.22KB
auth (invitation-status.js)1.22KB0.70KB
auth (org-roles.js)6.66KB2.78KB
auth (phone-identifier.js)1.11KB0.66KB
auth (types.js)0.59KB0.35KB
auth (useAuth.js)5.02KB0.88KB
auth (useIsWorkspaceAdmin.js)1.61KB0.85KB
collaboration (CommentThread.js)26.07KB7.56KB
collaboration (LiveCursors.js)3.17KB1.27KB
collaboration (PresenceAvatars.js)6.49KB2.64KB
collaboration (PresenceProvider.js)2.79KB1.13KB
collaboration (index.js)1.65KB0.73KB
collaboration (useCollaborationTranslation.js)6.05KB2.52KB
collaboration (useCommentSearch.js)1.98KB0.88KB
collaboration (useConflictResolution.js)7.75KB1.86KB
collaboration (useMentionNotifications.js)1.81KB0.68KB
collaboration (usePresence.js)6.33KB1.84KB
collaboration (useRealtimeSubscription.js)7.91KB2.01KB
components (index.js)506.17KB113.33KB
core (index.js)4.11KB1.62KB
create-plugin (index.js)10.08KB3.26KB
data-objectstack (index.js)159.03KB44.08KB
fields (index.js)237.07KB59.46KB
i18n (LocalizationContext.js)1.76KB0.96KB
i18n (currency.js)1.22KB0.64KB
i18n (i18n.js)4.28KB1.75KB
i18n (index.js)3.42KB1.39KB
i18n (pickLocalized.js)3.69KB1.73KB
i18n (provider.js)23.13KB7.63KB
i18n (useDisplayLocale.js)2.85KB1.45KB
i18n (useObjectLabel.js)29.43KB7.15KB
i18n (useSafeTranslation.js)7.77KB3.13KB
layout (index.js)39.16KB10.97KB
mobile (MobileProvider.js)0.92KB0.49KB
mobile (ResponsiveContainer.js)0.94KB0.38KB
mobile (breakpoints.js)1.51KB0.70KB
mobile (createOfflineDataSource.js)5.61KB1.74KB
mobile (index.js)1.50KB0.62KB
mobile (offlineQueue.js)3.91KB1.35KB
mobile (pwa.js)0.97KB0.49KB
mobile (serviceWorker.js)1.48KB0.62KB
mobile (serviceWorkerSource.js)3.41KB1.48KB
mobile (useBreakpoint.js)1.54KB0.65KB
mobile (useGesture.js)6.96KB1.98KB
mobile (useOfflineSync.js)1.99KB0.72KB
mobile (usePullToRefresh.js)2.53KB0.85KB
mobile (useResponsive.js)0.71KB0.42KB
mobile (useResponsiveConfig.js)1.36KB0.63KB
mobile (useSpecGesture.js)4.32KB1.64KB
mobile (useTouchTarget.js)1.01KB0.54KB
permissions (MePermissionsProvider.js)9.35KB3.31KB
permissions (PermissionContext.js)0.31KB0.25KB
permissions (PermissionGuard.js)0.89KB0.45KB
permissions (PermissionProvider.js)4.42KB1.42KB
permissions (evaluator.js)5.12KB1.74KB
permissions (index.js)0.91KB0.41KB
permissions (store.js)0.91KB0.42KB
permissions (useFieldPermissions.js)1.28KB0.52KB
permissions (usePermissions.js)1.81KB0.83KB
plugin-ai (index.js)15.75KB3.80KB
plugin-calendar (index.js)46.62KB12.83KB
plugin-charts (index.js)64.75KB18.37KB
plugin-chatbot (index.js)181.21KB43.14KB
plugin-dashboard (index.js)128.04KB32.75KB
plugin-designer (index.js)212.39KB42.83KB
plugin-detail (index.js)241.46KB60.56KB
plugin-editor (index.js)2.46KB1.10KB
plugin-form (index.js)123.77KB30.07KB
plugin-gantt (index.js)164.10KB39.87KB
plugin-grid (index.js)198.22KB53.27KB
plugin-kanban (index.js)52.93KB14.60KB
plugin-list (index.js)111.66KB27.13KB
plugin-map (index.js)19.96KB6.56KB
plugin-markdown (index.js)13.72KB4.69KB
plugin-report (index.js)42.84KB11.77KB
plugin-timeline (index.js)26.68KB7.66KB
plugin-tree (index.js)8.50KB2.88KB
plugin-view (index.js)84.08KB20.59KB
providers (DataSourceProvider.js)0.75KB0.39KB
providers (MetadataProvider.js)1.37KB0.59KB
providers (ThemeProvider.js)1.90KB0.85KB
providers (UploadProvider.js)11.66KB3.50KB
providers (index.js)0.44KB0.22KB
providers (types.js)0.01KB0.04KB
react-runtime (index.js)5.62KB2.34KB
react (LazyPluginLoader.js)3.77KB1.33KB
react (SchemaRenderer.js)31.56KB10.70KB
react (data-invalidation.js)5.05KB2.08KB
react (index.js)1.33KB0.69KB
react (schema-input.js)1.45KB0.83KB
react (spec-input.js)0.20KB0.18KB
sdui-parser (codegen.js)5.41KB2.34KB
sdui-parser (index.js)4.77KB2.16KB
sdui-parser (input-type.js)2.84KB1.40KB
sdui-parser (parse.js)10.76KB3.17KB
sdui-parser (provenance.js)3.66KB1.82KB
sdui-parser (types.js)0.29KB0.24KB
sdui-parser (validate.js)6.92KB2.40KB
types (ai.js)0.20KB0.17KB
types (api-types.js)0.20KB0.18KB
types (app.js)2.87KB0.99KB
types (base.js)0.20KB0.18KB
types (blocks.js)0.20KB0.18KB
types (complex.js)0.20KB0.18KB
types (crud.js)0.20KB0.18KB
types (dashboard-filter-alias.js)6.23KB2.74KB
types (data-display.js)0.20KB0.18KB
types (data-protocol.js)0.20KB0.19KB
types (data.js)0.20KB0.18KB
types (designer.js)1.87KB0.85KB
types (disclosure.js)0.20KB0.18KB
types (error-code.js)1.54KB0.88KB
types (feedback.js)0.20KB0.18KB
types (field-types.js)0.20KB0.18KB
types (form.js)0.20KB0.18KB
types (http-retry.js)4.32KB2.02KB
types (index.js)3.08KB1.53KB
types (layout.js)0.20KB0.18KB
types (managed-by.js)0.19KB0.18KB
types (mobile.js)2.59KB1.31KB
types (navigation.js)0.20KB0.18KB
types (objectql.js)0.20KB0.18KB
types (overlay.js)0.20KB0.18KB
types (permissions.js)0.20KB0.18KB
types (plugin-scope.js)0.20KB0.18KB
types (record-components.js)0.20KB0.19KB
types (record-semantics.js)1.28KB0.67KB
types (registry.js)0.20KB0.18KB
types (reports.js)0.20KB0.18KB
types (spec-report.js)5.05KB1.93KB
types (system-fields.js)3.33KB1.54KB
types (theme.js)0.20KB0.18KB
types (ui-action.js)3.40KB1.71KB
types (views.js)0.20KB0.18KB
types (widget.js)0.20KB0.18KB

Size Limits

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

@os-support-ai
os-support-ai marked this pull request as ready for review August 18, 2026 23:05
@os-support-ai
os-support-ai added this pull request to the merge queueAug 18, 2026
Merged via the queue into main with commit 2eb8db8Aug 18, 2026
22 checks passed
@os-support-ai
os-support-ai deleted the claude/issue-4266-in-predicate-array-diagnostic branch August 18, 2026 23:06
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

objectui: metadata-admin predicate in with a non-literal element silently becomes an empty set — membership false for every row, no diagnostic

2 participants

@os-support-ai@claude