包 :scripts/check-driver-conformance.mjs(#4363 引入的 driver conformance gate)
核实基线 :main @ 0a936ea,已实测复现 (下附命令与输出)
关联 :#4645 (driver 目录重组 packages/plugins/driver-* → packages/drivers/*)——这是那次重组的前置项,但本身独立成立
PR :#4648
摘要
gate 的发现根写死在 packages/plugins,而 listDir 吞掉 ENOENT 返回 []。audit 路径在发现零个 driver 时不报错,打印 OK — 0 covered cell(s) 并 exit 0。
先把范围说准,避免把它讲得比实际严重:今天 CI 拦得住 。lint.yml:304 跑的是 pnpm check:driver-conformance,而 package.json:50 把它定义成 --self-test && audit,self-test 里有一条 driver 发现断言会先失败。问题在于守卫只长在 self-test 上,audit 自己没有 ——而 audit 是脚本 header 第 21 行明确文档化的独立用法。
实测
把 DRIVERS_DIR 指向一个不存在的目录(即「目录改名了但常量没跟上」),两条路径:
$ node check-driver-conformance.mjs
driver conformance matrix (0 drivers x 5 case-sets)
driver FILTER_LOGIC TEMPORAL TEMPORAL_TIME PAGINATION PAGINATION_UNORDERED
check-driver-conformance: OK — 0 covered cell(s), 0 in the DEBT ledger, 0 exempt.
exit=0 ← 覆盖零个 driver,报 OK
$ node check-driver-conformance.mjs --self-test
x self-test: discovers driver packages from disk
check-driver-conformance --self-test: 1 failure(s).
exit=1 ← 这条拦住了
三条不变量为什么会全部空过
audit() 里:
errors 为空 → report() 走到 :318 打印 OK。空台账是预期的稳态 ,所以 RECONCILED 这条兜底在正常状态下恒为空——它挡不住这个洞。
根因:两条轴的不对称
更正 :本 issue 早前版本说「CASE_SETS_DIR 也没有任何守卫,该一并加固」——那是错的,实测它有守卫 。把 CASE_SETS_DIR 指向不存在的目录:
x CLASSIFIED: CASE_SETS names FILTER_LOGIC_CASES, which filter-logic-conformance.ts no longer exports.
x CLASSIFIED: CASE_SETS names TEMPORAL_CASES, ...
...(5 条,每个 case-set 一条)
check-driver-conformance: 5 problem(s). exit=1
给它再加一层是冗余的。
两条轴之所以一条会烂一条不会,差别在有没有一份声明的预期可供反向对账 :
轴
声明的预期
反向对账
目录失效时
case-set
CASE_SETS(脚本内 5 条)
CLASSIFIED 第二个方向
5 条 error
driver
无——纯磁盘发现
RECONCILED 遍历 LEDGER,而它按设计恒空
静默 OK
driver 轴不能靠「补一份清单」来修——那正好违反脚本 :145 的 /** Driver packages, from disk — never a hardcoded list. */。能声明的只有一条:零不是有效的发现结果 。
为什么仍然要修
文档化的用法会给出假绿。 header :21-22 把两条命令并列列出,直接跑 audit 是被鼓励的(本地迭代时谁都不想每次跑 self-test)。它对零发现返回 OK。
唯一的守卫硬编码了 driver 名和数量。 selfTest() :375:
expect ( 'discovers driver packages from disk' , drivers . length >= 3 && drivers . includes ( 'driver-sql' ) ) ;
而同一份脚本 :145 的注释是 /** Driver packages, from disk — never a hardcoded list. */。守卫违反了被守卫者的设计原则;>= 3 还会随 driver 增加而静默失去意义(现在 4 个,迁入 turso 后 5 个)。
失败信息不指向真因。 discovers driver packages from disk 不提 DRIVERS_DIR、不说路径已失效。driver-turso 住在闭源 cloud 仓,却是开源 runtime 点名偏好的默认 driver — 建议把核心迁回本仓 #4645 的重组正是要动这个常量,届时踩中的人拿到的是一句不知所云的自检失败。
这正是该脚本 header 自己点名要避免的形状——「a verifier that reports success while degrading(route-ownership rule 3)」。它把这条标准用在了被检查对象上,没用在自己身上。
audit() 增加第四条不变量 DISCOVERED ,检查体抽成 discoveredErrors(drivers) 以便 self-test 驱动不变量本身而非其替身;self-test 里的 driver-sql / >= 3 硬编码随之删除。失败信息带上实际搜索的目录:
x DISCOVERED: no driver package found under packages/drivers/. Either these
packages moved and DRIVERS_DIR is stale, or they are gone. Every other
invariant iterates the discovered set, so a zero-driver run reports OK having
checked nothing — it fails here instead.
case-set 轴按上面的实测结论不动 。
不做的代价
小,但方向错。gate 存在的理由就是「把缺失变成失败」;它自己在最基础的一格上把缺失变成了 OK。#4645 的重组会实际触发这一格,而那时诊断成本落在一个正在做别的事的人头上。
包:
scripts/check-driver-conformance.mjs(#4363 引入的 driver conformance gate)核实基线:
main@0a936ea,已实测复现(下附命令与输出)关联:#4645(driver 目录重组
packages/plugins/driver-*→packages/drivers/*)——这是那次重组的前置项,但本身独立成立PR:#4648
摘要
gate 的发现根写死在
packages/plugins,而listDir吞掉 ENOENT 返回[]。audit 路径在发现零个 driver 时不报错,打印OK — 0 covered cell(s)并 exit 0。先把范围说准,避免把它讲得比实际严重:今天 CI 拦得住。
lint.yml:304跑的是pnpm check:driver-conformance,而package.json:50把它定义成--self-test && audit,self-test 里有一条 driver 发现断言会先失败。问题在于守卫只长在 self-test 上,audit 自己没有——而 audit 是脚本 header 第 21 行明确文档化的独立用法。实测
把
DRIVERS_DIR指向一个不存在的目录(即「目录改名了但常量没跟上」),两条路径:三条不变量为什么会全部空过
audit()里:for (const driver of drivers)(:237),零 driver = 零次迭代 = 零 errorfor (const entry of LEDGER)(:271),而LEDGER = [](:134,filter-logic conformance 少了两个 backend:MongoDB 的 translateFilter 从来没被 #3774 的标准收编 #4405 起清空,注释写明「An empty ledger is the intended steady state」)= 零次迭代 = 零 errorCASE_SETS与磁盘上的*-conformance.ts,与 driver 轴无关,照常通过errors为空 →report()走到 :318 打印 OK。空台账是预期的稳态,所以 RECONCILED 这条兜底在正常状态下恒为空——它挡不住这个洞。根因:两条轴的不对称
两条轴之所以一条会烂一条不会,差别在有没有一份声明的预期可供反向对账:
CASE_SETS(脚本内 5 条)LEDGER,而它按设计恒空driver 轴不能靠「补一份清单」来修——那正好违反脚本
:145的/** Driver packages, from disk — never a hardcoded list. */。能声明的只有一条:零不是有效的发现结果。为什么仍然要修
selfTest():375:/** Driver packages, from disk — never a hardcoded list. */。守卫违反了被守卫者的设计原则;>= 3还会随 driver 增加而静默失去意义(现在 4 个,迁入 turso 后 5 个)。discovers driver packages from disk不提DRIVERS_DIR、不说路径已失效。driver-turso 住在闭源 cloud 仓,却是开源 runtime 点名偏好的默认 driver — 建议把核心迁回本仓 #4645 的重组正是要动这个常量,届时踩中的人拿到的是一句不知所云的自检失败。修法(#4648 已实施)
audit()增加第四条不变量 DISCOVERED,检查体抽成discoveredErrors(drivers)以便 self-test 驱动不变量本身而非其替身;self-test 里的driver-sql/>= 3硬编码随之删除。失败信息带上实际搜索的目录:case-set 轴按上面的实测结论不动。
不做的代价
小,但方向错。gate 存在的理由就是「把缺失变成失败」;它自己在最基础的一格上把缺失变成了 OK。#4645 的重组会实际触发这一格,而那时诊断成本落在一个正在做别的事的人头上。