test(drivers): filter-logic 标准收编第五个 backend —— driver-mongodb 与 driver-sqlite-wasm 两条 DEBT 同 PR 清账 (#4405) - #4596
Conversation
…lter-logic standard (#4405) `FILTER_LOGIC_CASES` (#3774) called itself the standard "the four independent FilterCondition backends" are checked against. There are five: `driver-mongodb`'s `translateFilter` is an independent implementation whose $and/$or/$not translation shares no code with the SQL compiler or the in-memory matcher, and it was missed rather than excluded. `driver-sqlite-wasm` inherits SqlDriver's compiler but had never run the table through its own sql.js engine. - `mongodb-filter-logic-translation.test.ts` — server-free: drives every shared case through `translateFilter` and evaluates the emitted MongoDB document over the shared fixture with a deliberately strict in-process reader (unmodelled shapes throw; a document-level `$not` throws by name, because the server rejects it). Wire-shape pins cover #4405's named risk areas ($not → $nor, nested $and inside $or), and negative controls keep the reader discriminating. - `mongodb-filter-logic-conformance.test.ts` — the same table against a real mongod via `createTestMongod`, skipping cleanly when the binary is unreachable. - `sqlite-wasm-filter-logic-conformance.test.ts` — the same table through the wasm driver's own engine. No translation change: `translateFilter` answers all seventeen cases correctly today. Both DEBT entries are deleted from `scripts/check-driver-conformance.mjs` in the same commit, so the matrix is ok/ok for both cells and the ledger is empty. The spec's "four backends" prose now says five and names the fifth. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012C2cd7tL8QDoZ2QKN3djJ5
|
The latest updates on your projects. Learn more about Vercel for GitHub. 1 Skipped Deployment
|
📓 Docs Drift CheckThis PR changes 1 package(s): 107 hand-written doc(s) reference the affected code and may need an implementation-accuracy re-verification:
|
|
CI 全绿(21 个 check,2 个被 path filter 跳过),其中最关键的一条 —— mongod 那半区在 CI 上真跑了,不是 skip。 driver-mongodb 的测试并不在 12 个文件全 passed、253 条全 passed、0 skipped —— 二进制下下来了,17 条共享用例是打在真 mongod 上过的,顺带也证明了这半区在非 UTC 进程时区下同样成立。真实引擎与无服务器求值器对这张表的回答一致,即「翻译层没有分歧」这个结论有两个独立证据。 Test Core (1/2) 里 wasm 那条: 🤖 Generated with Claude Code Generated by Claude Code |
Fixes #4405
问题
FILTER_LOGIC_CASES(#3774)的开篇说自己是「the four independent FilterCondition backends are each checked against」的共享标准。实际上有五个:driver-mongodb的translateFilter是完全独立的第五个实现,$and/$or/$not的翻译跟 SQL 编译器、内存匹配器一行代码都不共用 —— 它是被漏掉的,不是被排除的。而且它是唯一一个目标语言拼不出这套标准的 backend:MongoDB 根本没有文档级$not(服务端直接回unknown top level operator: $not),所以否定必须以$nor出去,分支自己的 key 必须留在同一个文档里、$and/$or子句被抬到它旁边。这条路线从来没被共享用例验证过。driver-sqlite-wasm继承SqlDriver的过滤编译器,但从没让这张表走过它自己的 sql.js 引擎。scripts/check-driver-conformance.mjs里的两条 DEBT 就是这两格,本 PR 同时清掉 —— 只删条目不写套件会挂CONSUMED,写了套件不删条目会挂RECONCILED,所以必须同一个 PR。改了什么
driver-mongodb把这张表跑两遍,拆分是刻意的:mongodb-filter-logic-translation.test.ts—— 无服务器,永远会跑。把每条共享用例喂给translateFilter,再把它吐出来的 MongoDB 查询文档在共享 fixture 上求值。translateFilter是纯函数,而mongodb-memory-server要从 fastdl.mongodb.org 下 ~123 MB 二进制 —— 「只有能下二进制的机器才抓得到的缺陷」在受限网络上等于没人抓得到,这也正是test-mongod.ts和 ObjectQL silently drops unsupported predicate keys;findOnethen returns the first row #4419 那对套件存在的理由。文件里那个进程内的求值器是刻意严格的:任何它没建模的形状一律
throw,而不是悄悄判 true —— 文档级$not会带着服务端的原话抛出来。比真实引擎更宽松的替身会把套件变成坏代码的绿灯(ObjectQL silently drops unsupported predicate keys;findOnethen returns the first row #4419 点名的那个坑),所以它自己的判别力也被钉住了:有几条用例要求「被放宽的文档必须让它所放宽的那条用例失败」,这样「全绿」就不可能等于「求值器对什么都点头」。filter-logic conformance 少了两个 backend:MongoDB 的 translateFilter 从来没被 #3774 的标准收编 #4405 点名的两个风险区还额外有字面 wire-shape 断言:
$not→$nor(且与同分支的兄弟 key 以$and相连)、$or分支里的嵌套$and保持嵌套而不是被摊平。mongodb-filter-logic-conformance.test.ts—— 同一张表打真 mongod(createTestMongod),回答前一半答不了的那个问题:MongoDB 同不同意。二进制拉不到时干净地跳过(不是静默通过);本环境 403 拉不到,所以本地是 skip,CI 会真跑。driver-sqlite-wasm的sqlite-wasm-filter-logic-conformance.test.ts让同一张表走它自己的引擎。编译器是继承来的,这里不重新实现任何东西;钉住的是另一半:嵌套的(… AND …) OR (… AND …)必须活着穿过那个自定义 sql.js dialect 的编译、绑参和回程 —— 跟它的 temporal / pagination 套件为各自子句覆盖的是同一个接缝。之所以当初记 DEBT 而不是 EXEMPT:「继承了所以没问题」正是那两个套件要否证的假设,而否证它的是套件,不是 ledger 条目。没有发现翻译分歧
translateFilter今天对全部 17 条共享用例的回答都是对的,$not在分支内、$and嵌在$or里都包括在内,所以本 PR 不改任何翻译逻辑。变的是:下一次改它的人没法悄悄放宽一个过滤条件。两个套件都验证过是有判别力而非装饰:把 #3774 的误编译重新引入(把
or传进分支自身的内容),mongodb 翻译套件 26 条里挂 15 条,wasm 套件 18 条里挂 13 条。另外把$nor换成文档级$not(也就是「MongoDB 有 $not 吧」这种想当然的改法)时,那条专门的不变量断言会点名报错。验证
ledger gate 的两个反向对照(都如注释所述地挂了):把 wasm 套件挪走 →
CONSUMED: driver-sqlite-wasm does not run FILTER_LOGIC_CASES;套件在但把条目加回去 →RECONCILED: driver-mongodb now runs FILTER_LOGIC_CASES …, but the ledger still carries a DEBT entry for it. Delete the entry.。--self-test也是绿的。CI 上要看的一点: 本地 mongod 拉不到,
mongodb-filter-logic-conformance.test.ts是 skip 的 —— 请在本 PR 的 CI 上确认它真的跑了(18 条,而不是 18 skipped)。顺带
packages/spec里filter-logic-conformance.ts的头注释和data/index.ts的导出注释原来写「four backends」,现在写五个并点名第五个 —— 纯注释,没有 schema、导出或生成物变化(check:generated全绿佐证)。🤖 Generated with Claude Code
Generated by Claude Code