Repository navigation
Description
越界发现,来自 objectstack#6936 的开发会话(objectui PR objectstack-ai/objectui#3937)。不在该 PR 范围内(#6936 的裁决只覆盖「解析不到的路径 → fail-open + 告警」),单独立单交 PM 分诊;未认领。
事实
packages/app-shell/src/views/metadata-admin/predicate.ts 的 == / != 分支左侧走 resolveValue(解析路径),右侧走 parseLiteral。parseLiteral 对「既不是引号串、也不是数字/布尔/null/数组」的输入原样返回该字符串(该函数末尾 return s;)。于是右侧写路径时,比较的是路径的字面文本,不是它的值。
实测读数(objectui worktree,origin/main @ 230ffd8 + PR #3937 分支;临时 vitest 探针,已删):
ctx = { data: { a: 'x', b: 'x' } } // 两侧值相等
data.a == data.b -> false // 期望 true
data.a != data.b -> true // 期望 false
ctx = { data: { a: 'x', b: 'y' } } // 两侧值不等
data.a == data.b -> false // 恰好"对",但理由是错的
data.a == 'x' -> true // 字面量对照组,正常
即 data.a == data.b 恒假、data.a != data.b 恒真,与两侧实际值无关:'x' === 'data.b'。
为什么是 observation-class(建议 finding,未打 pm:queue)
今天没有生产者踩到:安装版 @objectstack/spec 17.0.0-rc.5 里 metadata-admin 会渲染的四张表单(objectForm / pageForm / viewForm / actionForm)的谓词全部是 path == 字面量 / path in [字面量…] 形状,右侧无路径。文件头也明确写了它只支持一个子集("Supported subset (covers everything used in spec *.form.ts today)"),所以严格说这是已声明的子集边界,不是违约。
但它与 #6936 刚修掉的那条同族、且不被 #6936 的新告警覆盖:告警挂在 resolveValue 的根标识符检查上,而右侧根本不经过 resolveValue。所以一旦将来 spec 下发一条 data.a == data.b 形状的谓词,症状仍然是静默的错误结论(字段该显示时不显示),控制台一片安静 —— 正是 #6936 花一整张卡换掉的那种不可诊断形状。严重度按 filing-time 判断不可靠,交 PM 分诊定级。
可能的方向(不在此单里做决定)
- A. 右侧也走路径解析:
parseLiteral认不出的裸标识符改为按路径解析,解析不到则复用 objectui: metadata-admin 谓词求值器对「无法解析的路径」静默判假(fail-CLOSED),与文件自述的 fail-open 承诺相反 #6936 的 fail-open + 告警。风险:data.type == text这种「本意是字符串却漏了引号」的写法从"恰好能用"变成 fail-open 判真。 - B. 只加诊断,不改语义:
parseLiteral走到末尾那条return s且输入长得像路径(含.或匹配标识符文法)时发 dev 告警,点名「右侧被当作字符串字面量」。语义零变化,把子集边界变成可发现的事实。 - C. 交给真正的 CEL:文件头本来就说自己是
@objectstack/formula的临时替身(ROADMAP M9),换成真 CEL 求值器后本条自动消失。 - D. 生产端拦住:发布期校验谓词表达式(objectui: metadata-admin 谓词求值器对「无法解析的路径」静默判假(fail-CLOSED),与文件自述的 fail-open 承诺相反 #6936 的伴生卡)可以把「右侧是路径」这类超出渲染器子集的写法在授权门口拒掉,契约优先。
倾向 B + D(渲染器只把边界说清,语义修正交给 C/D,避免在消费端加宽容),但这是求值语义取舍,应由维护者定。
查重说明
搜过 open issues:evaluatePredicate(仅命中 #6936 本身)、parseLiteral predicate.ts 0 命中、metadata-admin predicate right-hand identifier 0 命中、谓词 求值器 字面量 仅命中 PM 登记表 #4604、objectui 仓 predicate literal right side 0 命中。若有同小时孪生单,按惯例 race-close 本单。
Activity
os-zhuang commentedon Aug 10, 2026
Finding-triage ruling: Promote —
findingtopm:queue, scoped to the diagnostic-only leg (the card's option B).metadata-admin's predicate evaluator resolves the left side of == / != but parses the right side as a string literal (predicate.ts:175-176, :269 fallthrough), so
data.a == data.bis always false with zero diagnostics — the no-silent-misjudgment invariant #6936 restored is still open on this leg (its warning hangs on resolveValue, which the right side never reaches). Semantic options A/C/D stay undecided and are out of scope for the queued card.Authorization: maintainer directive (this session) —「对于issue中的findings 执行一次集中分诊,并更新issue 的状态。」Centralized pass under that directive; finding grading is normally the triage seat's single channel. Round: objectstack#4949 finding-triage, 2026-08-10.
Session: 01JaVVMrSxt7Tgi1uwEuDtH7
Generated by Claude Code
os-zhuang commentedon Aug 10, 2026
Migrated to objectstack-ai/objectui#4049 under #7167 (file-at-destination ruling, maintainer 2026-08-10). Native GitHub issue transfer is not available to this session's credential, so the card was recreated at the destination; this thread stays as the authoritative history and is linked from the new card. Closing as not planned here — moved, not rejected.
Generated by Claude Code