发现于 #3601 / PR #3623(修那单时顺手排查同类结构,未在该 PR 修)。
现象
两个 spec 平价测试各自维护一个排除集,从 spec 派生的 VIEW_FILTER_OPERATORS 里减去同样两个 token:
packages/plugin-list/src/__tests__/filter-operator-ast-parity.test.ts:35 —— HANDLED_BEFORE_MAPPING = new Set(['is_empty', 'is_not_empty'])
packages/data-objectstack/src/filter-operator-ast-parity.test.ts:34 —— NOT_THIS_ADAPTERS_JOB = new Set(['is_empty', 'is_not_empty'])
两处的排除理由都成立(视图层在 mapOperator 被问到之前就把这两个改写成 [field, '=' | '!=', null],所以它们不需要 AST 拼写)。缺的是排除项本身的存活断言:没有任何一条断言 is_empty / is_not_empty 仍然是 VIEW_FILTER_OPERATORS 的成员。
一旦上游把这两个 token 从视图词表里退役或改名,排除集就变成一次空减法 —— 平价扫描依然全绿(它对剩下的 token 仍然是完整的),但排除行成了死重,注释还会继续告诉读者「视图层会先改写这两个」,而那时视图词表里已经没有它们了。
现状测量(objectui origin/main,@objectstack/spec@17.0.0-rc.5)
VIEW_FILTER_OPERATORS count: 19
is_empty LIVE in spec
is_not_empty LIVE in spec
今天两条都还在,排除是有效的 —— 这条是预防性的,不是已兑现的腐化。
为什么标 finding
今天没有用户会碰到:测试绿,行为无影响,排除项当前全部有效。代价是结构性的 —— 这正是 #3601 里 82 条拒绝名单烂掉 37 条的同一个形状:一份手写清单挂在 spec 派生的词表旁边,却没有一条断言清单成员仍然存在于那份词表。#3601 的 37 条恰恰是没人给它加存活断言,才一路积累到只有做审计时才被量出来。
对照组:仓里同类结构里,有两处已经把这件事做对了,可以直接抄——
反过来,FlowReferenceField.specDerivation.test.ts 的 EXPECTED_KINDS 是双向 pin + 显式反空断言,不属此类,无需处理。
建议处置(供参考,非结论)
每个文件加三行,与 PR #3568 同手法:
it('every excluded operator is still in the spec view vocabulary', () => {
for (const op of HANDLED_BEFORE_MAPPING) {
expect(
VIEW_FILTER_OPERATORS.includes(op),
`'${op}' is excluded from the bridge sweep but the spec no longer lists it`,
).toBe(true);
}
});
严重性交 PM triage 判定,不自评。
Generated by Claude Code
发现于 #3601 / PR #3623(修那单时顺手排查同类结构,未在该 PR 修)。
现象
两个 spec 平价测试各自维护一个排除集,从 spec 派生的
VIEW_FILTER_OPERATORS里减去同样两个 token:packages/plugin-list/src/__tests__/filter-operator-ast-parity.test.ts:35——HANDLED_BEFORE_MAPPING = new Set(['is_empty', 'is_not_empty'])packages/data-objectstack/src/filter-operator-ast-parity.test.ts:34——NOT_THIS_ADAPTERS_JOB = new Set(['is_empty', 'is_not_empty'])两处的排除理由都成立(视图层在
mapOperator被问到之前就把这两个改写成[field, '=' | '!=', null],所以它们不需要 AST 拼写)。缺的是排除项本身的存活断言:没有任何一条断言is_empty/is_not_empty仍然是VIEW_FILTER_OPERATORS的成员。一旦上游把这两个 token 从视图词表里退役或改名,排除集就变成一次空减法 —— 平价扫描依然全绿(它对剩下的 token 仍然是完整的),但排除行成了死重,注释还会继续告诉读者「视图层会先改写这两个」,而那时视图词表里已经没有它们了。
现状测量(objectui
origin/main,@objectstack/spec@17.0.0-rc.5)今天两条都还在,排除是有效的 —— 这条是预防性的,不是已兑现的腐化。
为什么标
finding今天没有用户会碰到:测试绿,行为无影响,排除项当前全部有效。代价是结构性的 —— 这正是 #3601 里 82 条拒绝名单烂掉 37 条的同一个形状:一份手写清单挂在 spec 派生的词表旁边,却没有一条断言清单成员仍然存在于那份词表。#3601 的 37 条恰恰是没人给它加存活断言,才一路积累到只有做审计时才被量出来。
对照组:仓里同类结构里,有两处已经把这件事做对了,可以直接抄——
packages/fields/src/widgets/__tests__/FilterConditionField.operators.test.ts:117—— PR chore(deps): track the @objectstack family at 17.0.0-rc.5 and restore green #3568 给KNOWN_UNREACHABLE加的「每个排除 token 仍是 spec operator」断言。packages/plugin-charts/src/__tests__/chart-type-spec-parity.test.tsx——TRACKED_DIALECT在 spec 收编条目时console.info提示删除,并在注释里写明它是上界而非期望。反过来,
FlowReferenceField.specDerivation.test.ts的EXPECTED_KINDS是双向 pin + 显式反空断言,不属此类,无需处理。建议处置(供参考,非结论)
每个文件加三行,与 PR #3568 同手法:
严重性交 PM triage 判定,不自评。
Generated by Claude Code