Skip to content

fix(framework): 可见性谓词求值失败去静默——每谓词 warn 一次带源文本与原因 (#5149) - #3541

Merged
hotlong merged 1 commit into
mainfrom
claude/issue-5149-predicate-loud-warn
Aug 7, 2026
Merged

fix(framework): 可见性谓词求值失败去静默——每谓词 warn 一次带源文本与原因 (#5149)#3541
hotlong merged 1 commit into
mainfrom
claude/issue-5149-predicate-loud-warn

Conversation

@hotlong

@hotlong hotlong commented Aug 7, 2026

Copy link
Copy Markdown
Contributor

Refs objectstack-ai/objectstack#5149(⛔ 非 Fixes——诉求 1 仍在决策箱,本 PR 不关闭该 issue)

按维护者半裁(2026-08-06 10:39Z)落地已放行半边:诉求 2(求值失败去静默)+ 诉求 4(record. 绑定文档验收)。

改了什么(诉求 2)

issue 摘的混淆产物 function A(e,t,n,r,i)@object-ui/coreevalFieldPredicate(packages/core/src/evaluator/fieldRules.ts)。三种失败形状——表达式 parse 失败、ExpressionEngine.evaluate 返回 not-ok、防御性 catch 捕获 throw——现在都:

  • console.warn 恰好一次(模块级按「谓词文本」去重,dialect+source 为键,JSON 编码——不用控制字符分隔,objectstack#5450 教训),内容含:谓词源文本、引擎失败原因([kind] message)、调用点提供的定位信息(如 visibleWhen of field 'amount')、实际采用的默认值;
  • 返回值一丝不变:仍返回调用方传入的默认(可见性 true / readonly-required false)。fail-open 默认值本身 ⛔ 未动——那是诉求 1,维护者单独拍板;本诊断落地正是给 1 的拍板提供命中面数据。

定位信息线程化(有多少上下文给多少):

  • resolveFieldRuleState 新增可选 fieldContext,warn 报 visibleWhen/readonlyWhen/requiredWhen of field 'x';
  • form.tsx 渲染门与 error-clearing effect、WizardForm 必填门、ScreenView 屏幕字段、optionRules 选项级、listConditional 格式化 fast path(带 conditionalFormatting[i] 标签)全部传入定位;
  • 故障探测型调用方(evalRowPredicate fail-closed 路径、ExpressionEvaluator.throwOnError——两处都是双求值探测)传 warn: false,保留自己原有的单条诊断:每个坏谓词全局恰好一条 warn,listConditional 既有计数断言不破。

措辞对齐服务端「log and allow」惯例(readonlyWhen for 'x' failed to evaluate — change allowed through)与仓内既有 warnEvalError 风格([object-ui] 前缀、Set 去重、JSON.stringify 源文本)。文档同步:ADR-0036 增补 Amendment、content/docs/guide/metadata-diagnostics.md 增补运行时诊断段。

测试(全部实跑)

  • 新增 8 条 pin(fieldRules.test.ts「failure diagnostics」describe):坏谓词(unbound identifier / 语法错误)warn 恰好一次且含源文本+原因+默认值;同文本重复求值不再 warn;好/空/null 谓词零 warn;真 FALSE 不 warn;warn: false 抑制;context 定位;resolveFieldRuleState 规则种类+字段定位;引擎 throw 形状([throw]);
  • listConditional 两条既有测试升级为断言新行为(fast path 一条 warn、格式化规则带定位),warnOnError 探测路径既有计数断言原样通过;
  • 逆向验证(先定方向再跑):仅回退 fieldRules.ts 源码改动、保留测试 ⇒ 预测恰好 7 条 warn 断言变红、39 条值契约保持绿——实测严丝合缝(5 红 fieldRules + 2 红 listConditional,39 绿),已恢复;
  • pnpm exec vitest run packages/core/ packages/components/ packages/plugin-form/ ⇒ 187 files / 2418 tests 全绿;
  • pnpm exec vitest run packages/app-shell/src/views/ ⇒ 180 files / 1585 tests 全绿(1 skipped 既有);
  • turbo run type-check lint(core / components / plugin-form / app-shell)⇒ 36/36 任务成功;
  • node scripts/check-control-bytes.mjs ⇒ OK。

诉求 4 验收(文档半边——判定:已存在,零改动)

裁决指向的 describe 在 objectstack 仓 packages/spec/src/ui/view.zod.ts(origin/main)已完整:

  • :1407-1413(JSDoc)与 :1414(describe):明确「Root: record+current_user (runtime forms) or data (metadata forms)」,示例即 record. 前缀写法(record.priority == 'urgent');
  • :1505-1508:FormSection 级同样声明;
  • 无任何诱导裸标识符的示例(Repro 1 根源)。按最小改动原则不另开 objectstack PR。

范围红线(照裁决)

  • ⛔ fail-open 默认值未动(诉求 1 在决策箱,求值失败仍返回既有默认);
  • ⛔ 无构建期 lint(诉求 3 已另立 objectstack#6128 归 devx);
  • ⛔ 未触碰 objectstack 仓 packages/console/dist(本 PR 全部在 objectui 源码)。

Changeset

.changeset/predicate-eval-failures-warn-once.md——四包 patch(行为不变、纯诊断增强)。


Generated by Claude Code

Refs objectstack-ai/objectstack#5149 (appeal 2 of the half-approved ruling,
2026-08-06). evalFieldPredicate now logs one console.warn per predicate text
on any evaluation failure (parse / not-ok / throw), with the predicate
source, the engine's failure reason, and the caller's field/rule locator.
Verdicts are byte-for-byte unchanged: still fail-open to the caller's safe
default — flipping that default is appeal 1, deliberately NOT in this change.
Fault-probing callers (evalRowPredicate fail-closed path, ExpressionEvaluator
throwOnError) opt out via diagnostic.warn=false and keep their own single
diagnostic, so no broken predicate ever warns twice.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015a5qkLzpGXhLL2F5gvJ7dD
@vercel

vercel Bot commented Aug 7, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
objectui Ignored Ignored Aug 7, 2026 3:28am

Request Review

@github-actions

github-actions Bot commented Aug 7, 2026

Copy link
Copy Markdown
Contributor

✅ Console Performance Budget

Metric Value Budget
Main entry (gzip) 28.1 KB 350 KB
Entry file index-DJ3VWWnB.js
Status PASS

📦 Bundle Size Report

Package Size Gzipped
app-shell (index.js) 8.66KB 3.13KB
app-shell (runtime-config.js) 7.42KB 2.32KB
app-shell (types.js) 0.01KB 0.04KB
app-shell (urlParams.js) 7.57KB 2.97KB
auth (AuthContext.js) 0.31KB 0.24KB
auth (AuthGuard.js) 1.17KB 0.53KB
auth (AuthProvider.js) 22.10KB 4.37KB
auth (AuthShell.js) 3.49KB 1.40KB
auth (ForgotPasswordForm.js) 12.21KB 3.45KB
auth (LoginForm.js) 18.13KB 5.39KB
auth (PreviewBanner.js) 0.90KB 0.50KB
auth (RegisterForm.js) 6.64KB 2.21KB
auth (SocialSignInButtons.js) 9.60KB 3.89KB
auth (UserMenu.js) 3.40KB 1.22KB
auth (auth-gate-events.js) 1.29KB 0.66KB
auth (authStyles.js) 5.04KB 1.72KB
auth (createAuthClient.js) 35.76KB 9.11KB
auth (createAuthenticatedFetch.js) 4.37KB 1.69KB
auth (index.js) 2.35KB 1.07KB
auth (org-roles.js) 6.66KB 2.78KB
auth (phone-identifier.js) 1.11KB 0.66KB
auth (types.js) 0.59KB 0.35KB
auth (useAuth.js) 4.91KB 0.87KB
auth (useIsWorkspaceAdmin.js) 1.61KB 0.85KB
collaboration (CommentThread.js) 26.07KB 7.56KB
collaboration (LiveCursors.js) 3.17KB 1.27KB
collaboration (PresenceAvatars.js) 6.49KB 2.64KB
collaboration (PresenceProvider.js) 2.79KB 1.13KB
collaboration (index.js) 1.65KB 0.73KB
collaboration (useCollaborationTranslation.js) 6.05KB 2.52KB
collaboration (useCommentSearch.js) 1.98KB 0.88KB
collaboration (useConflictResolution.js) 7.75KB 1.86KB
collaboration (useMentionNotifications.js) 1.81KB 0.68KB
collaboration (usePresence.js) 6.33KB 1.84KB
collaboration (useRealtimeSubscription.js) 7.91KB 2.01KB
components (index.js) 479.87KB 105.52KB
core (index.js) 2.47KB 0.91KB
create-plugin (index.js) 9.28KB 2.98KB
data-objectstack (index.js) 136.30KB 34.76KB
fields (index.js) 229.82KB 56.53KB
i18n (LocalizationContext.js) 1.76KB 0.96KB
i18n (currency.js) 1.22KB 0.64KB
i18n (i18n.js) 4.32KB 1.77KB
i18n (index.js) 2.65KB 1.06KB
i18n (pickLocalized.js) 1.70KB 0.83KB
i18n (provider.js) 9.48KB 3.27KB
i18n (useObjectLabel.js) 26.14KB 6.07KB
i18n (useSafeTranslation.js) 4.52KB 1.96KB
layout (index.js) 38.53KB 10.71KB
mobile (MobileProvider.js) 0.92KB 0.49KB
mobile (ResponsiveContainer.js) 0.94KB 0.38KB
mobile (breakpoints.js) 1.51KB 0.70KB
mobile (createOfflineDataSource.js) 5.61KB 1.74KB
mobile (index.js) 1.50KB 0.62KB
mobile (offlineQueue.js) 3.91KB 1.35KB
mobile (pwa.js) 0.97KB 0.49KB
mobile (serviceWorker.js) 1.48KB 0.62KB
mobile (serviceWorkerSource.js) 3.41KB 1.48KB
mobile (useBreakpoint.js) 1.54KB 0.65KB
mobile (useGesture.js) 6.96KB 1.98KB
mobile (useOfflineSync.js) 1.99KB 0.72KB
mobile (usePullToRefresh.js) 2.53KB 0.85KB
mobile (useResponsive.js) 0.71KB 0.42KB
mobile (useResponsiveConfig.js) 1.36KB 0.63KB
mobile (useSpecGesture.js) 4.05KB 1.53KB
mobile (useTouchTarget.js) 1.01KB 0.54KB
permissions (MePermissionsProvider.js) 8.75KB 3.06KB
permissions (PermissionContext.js) 0.31KB 0.25KB
permissions (PermissionGuard.js) 0.89KB 0.45KB
permissions (PermissionProvider.js) 3.67KB 1.12KB
permissions (evaluator.js) 4.41KB 1.44KB
permissions (index.js) 0.91KB 0.41KB
permissions (store.js) 0.91KB 0.42KB
permissions (useFieldPermissions.js) 1.28KB 0.52KB
permissions (usePermissions.js) 1.55KB 0.71KB
plugin-ai (index.js) 15.71KB 3.79KB
plugin-calendar (index.js) 44.98KB 12.37KB
plugin-charts (index.js) 61.04KB 17.31KB
plugin-chatbot (index.js) 180.09KB 42.72KB
plugin-dashboard (index.js) 112.03KB 28.88KB
plugin-designer (index.js) 210.51KB 42.51KB
plugin-detail (index.js) 232.79KB 57.42KB
plugin-editor (index.js) 2.46KB 1.10KB
plugin-form (index.js) 111.63KB 26.99KB
plugin-gantt (index.js) 162.55KB 39.57KB
plugin-grid (index.js) 185.25KB 49.08KB
plugin-kanban (index.js) 48.03KB 13.22KB
plugin-list (index.js) 104.72KB 25.36KB
plugin-map (index.js) 16.81KB 5.24KB
plugin-markdown (index.js) 13.72KB 4.69KB
plugin-report (index.js) 40.58KB 10.58KB
plugin-timeline (index.js) 25.76KB 7.33KB
plugin-tree (index.js) 8.50KB 2.88KB
plugin-view (index.js) 84.03KB 20.55KB
providers (DataSourceProvider.js) 0.75KB 0.39KB
providers (MetadataProvider.js) 1.37KB 0.59KB
providers (ThemeProvider.js) 1.90KB 0.85KB
providers (UploadProvider.js) 11.71KB 3.53KB
providers (index.js) 0.44KB 0.22KB
providers (types.js) 0.01KB 0.04KB
react-runtime (index.js) 5.67KB 2.37KB
react (LazyPluginLoader.js) 3.77KB 1.33KB
react (SchemaRenderer.js) 19.28KB 6.38KB
react (data-invalidation.js) 5.05KB 2.08KB
react (index.js) 1.02KB 0.55KB
react (spec-input.js) 0.20KB 0.18KB
sdui-parser (codegen.js) 4.09KB 1.74KB
sdui-parser (index.js) 4.47KB 2.03KB
sdui-parser (parse.js) 10.04KB 2.82KB
sdui-parser (types.js) 0.29KB 0.24KB
sdui-parser (validate.js) 4.69KB 1.48KB
types (ai.js) 0.20KB 0.17KB
types (api-types.js) 0.20KB 0.18KB
types (app.js) 2.87KB 0.99KB
types (base.js) 0.20KB 0.18KB
types (blocks.js) 0.20KB 0.18KB
types (complex.js) 0.20KB 0.18KB
types (crud.js) 0.20KB 0.18KB
types (data-display.js) 0.20KB 0.18KB
types (data-protocol.js) 0.20KB 0.19KB
types (data.js) 0.20KB 0.18KB
types (designer.js) 1.87KB 0.85KB
types (disclosure.js) 0.20KB 0.18KB
types (error-code.js) 1.54KB 0.88KB
types (feedback.js) 0.20KB 0.18KB
types (field-types.js) 0.20KB 0.18KB
types (form.js) 0.20KB 0.18KB
types (http-retry.js) 4.32KB 2.02KB
types (index.js) 2.46KB 1.21KB
types (layout.js) 0.20KB 0.18KB
types (managed-by.js) 0.19KB 0.18KB
types (mobile.js) 0.20KB 0.18KB
types (navigation.js) 0.20KB 0.18KB
types (objectql.js) 0.20KB 0.18KB
types (overlay.js) 0.20KB 0.18KB
types (permissions.js) 0.20KB 0.18KB
types (plugin-scope.js) 0.20KB 0.18KB
types (record-components.js) 0.20KB 0.19KB
types (record-semantics.js) 1.28KB 0.67KB
types (registry.js) 0.20KB 0.18KB
types (reports.js) 0.20KB 0.18KB
types (spec-report.js) 5.05KB 1.93KB
types (system-fields.js) 3.33KB 1.54KB
types (theme.js) 0.20KB 0.18KB
types (ui-action.js) 3.40KB 1.71KB
types (views.js) 0.20KB 0.18KB
types (widget.js) 0.20KB 0.18KB

Size Limits

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

@hotlong
hotlong marked this pull request as ready for review August 7, 2026 03:33
@hotlong
hotlong added this pull request to the merge queue Aug 7, 2026
Merged via the queue into main with commit a4cff5b Aug 7, 2026
19 checks passed
@hotlong
hotlong deleted the claude/issue-5149-predicate-loud-warn branch August 7, 2026 03:33
Sign up for free to 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.

2 participants