Repository navigation
Description
范围外发现,来自 #5482(PR 见该单)的实现过程。#5482 的规则刻意只判两种可证形状,这条记录它没判的那一格,以及为什么补它需要一份共享谓词而不是第四份手抄。
事实
#5482 落地的 flow-multi-write-unfiltered 只在两种形状下告警(packages/lint/src/lint-flow-patterns.ts 的 filterCarriesNoCondition):
filter键缺失;filter是零个自有键的普通对象({})。
空组合子数组不在其中,而其中一种确实是整表写:
| 形状 | 平台已裁定的语义 | 是否整表写 | 当前是否告警 |
|---|---|---|---|
filter: { $and: [] } |
TRUE(AND 恒等元,#5322/#5134) | 是 —— multi: true 下删/改每一行 |
否 |
filter: { $or: [] } |
FALSE(OR 恒等元) | 否(一行都不匹配) | 否(正确) |
filter: { $not: {} } |
FALSE(NOT TRUE) | 否 | 否(正确) |
filter: { $or: [ {} ] } |
TRUE({} 是 TRUE 析取项,吸收整个 $or) |
是 | 否 |
裁定不是猜的,三个 driver 都实现了它:packages/drivers/driver-sql/src/sql-driver.ts 的 reduceFilterNode 与其上方 applyFilterCondition 的 "Boolean identities (#5134)" 注释、packages/drivers/driver-mongodb/src/mongodb-filter.ts:139 的同名函数、packages/drivers/driver-memory/src/memory-matcher.ts:44-85 的 evaluate,并由 packages/spec/src/data/filter-logic-conformance.ts 的共享 case-set 钉住(empty $and is TRUE / empty $or is FALSE / a {} branch is a TRUE disjunct and absorbs its $or)。
所以 config: { objectName: 'lead', filter: { $and: [] }, multi: true } 今天可写、可跑、清空整表,而 authoring 期一声不响 —— 与 #5482 的原始形状同类,只是拼法更少见。
为什么 #5482 没顺手补
判「哪个恒等元」需要那套布尔身份归约。它已经存在三份(上面三个 driver),规约来源是 spec 的 case-set 而不是一个可复用的函数。在 linter 里手写第四份,正是 packages/objectql/src/engine-delete-dispatch.ts 被抽出来防的那种事故:扫描器与校验器用两个不同的谓词回答同一个问题,某天其中一个被改。#5240 的 { field: {} } 三个答案、#4434 的假引擎比真引擎宽松,都是同一族。
建议方向(不预设结论)
- 把归约提到共享层:在
packages/spec暴露一个纯谓词(reduceFilterVerdict(node) -> 'true' | 'false' | 'clause',与FILTER_LOGIC_CASES同处一地并由它证明),三个 driver 各自的reduceFilterNode改为消费它,lint 侧filterCarriesNoCondition也消费它 —— 一个概念一个实现。工作量最大,但这是唯一让「declared = enforced」在四个消费者之间成立的形状。 - 只在 lint 侧近似:识别
$and: []这一种拼法。便宜,但立刻就是第四份归约的开头,且对$or: [ {} ]这类嵌套形状仍然沉默 —— 不建议。 - 不做:记录在规则的 JSDoc 里(
multi: true且filter为空的 delete_record / update_record 是「按声明清空整个对象」,authoring 期零诊断 —— #3810 的守卫按「条件被抹掉」判定,不按「条件为空」判定 #5482 已经这么记了),把这格留给 code review。
倾向 1。它同时改善另一条轴:AI 生成的 filter builder 掉光条件后 emit 的正是空组合子,而共享谓词让「空组合子等于什么」在四个消费者处只有一个答案,而不是四处各自宽容。
关联:#5482(引入这条规则的单)、#5322 / #5134(恒等元裁定)、#5240(零算子字段约束,同族先例)、#4550 / #4434(为什么共享谓词而不是手抄)。
Activity
os-zhuang commentedon Aug 5, 2026
分诊:决策类(
needs-user-decision)+ 预挂domain:spec。$and: []/$or: [{}]整表写零告警)已核origin/main成立——packages/lint/src/lint-flow-patterns.ts:700的filterCarriesNoCondition仍只判缺失与{}两种形状。但修向三选一里,作者倾向的方向 1 要在packages/spec新增一个公开导出的共享谓词(reduceFilterVerdict)并让 4 个消费者收编——这是契约面新增,超出分诊可代裁范围;方向 2 正文已自证不可取;方向 3 = 接受该格留白。需要维护者对 appetite 拍板。packages/spec(与FILTER_LOGIC_CASES同地),故预挂domain:spec。Blocked-by:;其中 driver-memory / driver-mongodb 两族的收编届时按 [裁决] driver-memory / driver-mongodb 投入冻结 —— 维护者 2026-08-05 口径(跨单锚点) #5499 冻结令单判(纯重构无用户面缺陷的话挂pm:on-hold),driver-sql 不受影响。multi: true且filter为空的 delete_record / update_record 是「按声明清空整个对象」,authoring 期零诊断 —— #3810 的守卫按「条件被抹掉」判定,不按「条件为空」判定 #5482(规则本体,PR feat(lint):multi: true且无 filter 的 delete/update 在 authoring 期告警(#5482) #5663 已合入)、空组合子在同仓有两个对立答案:五个后端归约成布尔单位元,service-analytics 的两个编译器 fail-closed 抛错 —— #5239 的一致性表四条因此进不了表 #5322/SqlDriver.applyFilterCondition 丢弃编译成空的 $and/$or 子过滤器,而不是套用布尔单位元 —— 与同仓 matchesFilterCondition / driver-memory 相反 #5134(恒等元裁定)均为上游既成事实,非重复。本评论来自分诊座位 Routine(#5474 试点),不构成认领。
Generated by Claude Code
os-zhuang commentedon Aug 6, 2026
维护者裁决(2026-08-06,经本会话转达):取方案 1 —— 布尔身份归约提为
packages/spec共享纯谓词(reduceFilterVerdict(node) → 'true' | 'false' | 'clause',与FILTER_LOGIC_CASES同处并由它证明),三个 driver 的reduceFilterNode与 lint 的filterCarriesNoCondition改为消费它——一个概念一个实现。方案 2 明确否决(第四份手抄);方案 3 否决(数据安全面不留给 code review)。实施要点(写进派发词):
$and: []、$or: [{}])的告警断言;needs-user-decision→pm:queue。会话:session_01N3uGFF8teXbpgtbEJ1aYXuGenerated by Claude Code
hotlong commentedon Aug 7, 2026
Release-board audit (maintainer-directed re-audit of non-board
domain:specitems, 2026-08-07): addingtarget:v17— metadata-protocol change, size M, low-risk: maintainer already ruled option 1 (new spec exportreduceFilterVerdict); three drivers + lint consume it mechanically and behavior stays pinned by the FILTER_LOGIC_CASES conformance gates. Closes thefilter: { $and: [] } + multi: truefull-table-delete blind spot. Maintainer directive: protocol changes land in v17 unless large/risky. Triage seat may veto.Generated by Claude Code
docs(lint): re-anchor the dead tracker citations in packages/lint/src…
fix(spec): conformance-case notes and names state each decision in wo…