|
7 | 7 | * 灰字」。判据取「文件 → 行数」而非「逐行原文」(与 `zIndex.guard` 刻意不同):逐行 key 会在拆件 / |
8 | 8 | * 行号漂移时把命中变成新增 ⇒ 假红。 |
9 | 9 | * |
| 10 | + * ★ 牙齿(评审 M-1 的结清):③ 用「迁移面(0) ∪ 残留面(1)」钉死冻结表每一格 + `TOTAL == RESIDUAL.length` |
| 11 | + * 独立校验和 ⇒「总数 + 某一残留格同时抬高」不再自洽。 |
| 12 | + * |
10 | 13 | * ★ 扫描口径(与 `tmp/scan-callsites.mjs` / T1 的 loading 类**同源**) |
11 | 14 | * ① 域 = `app/src/**` 的 `.ts`/`.tsx` 减 `*.test.ts(x)` 减 `ui/primitives/**` 减 `ui/icons/**`; |
12 | 15 | * ② 先剥注释(抹等长空白保行号);字符串/模板只跳过不抹内容 —— 判据读的正是可见文案; |
@@ -211,17 +214,21 @@ describe("加载态棘轮(B11):基线随迁移只降不升(冻结 18 → |
211 | 214 | ); |
212 | 215 | }); |
213 | 216 |
|
214 | | - it("③ 基线自洽:冻结总数 == 逐文件之和(只手改总数 ⇒ 这里红)", () => { |
| 217 | + it("③ 基线自洽:表被完全钉死(键集 == 迁移面 ∪ 残留面 · 总数 == 残留条目数)", () => { |
215 | 218 | const sum = Object.values(FROZEN_LOADING_TEXT_BY_FILE).reduce((a, b) => a + b, 0); |
216 | 219 | expect(sum, "冻结总数与逐文件之和不等(改基线必须两处同改,且只许往小改)").toBe(FROZEN_LOADING_TEXT_TOTAL); |
217 | 220 | // 实测**低于**冻结是允许的(别的单元先迁走 / 本棘轮尚未收紧):棘轮只保证"不升"。 |
218 | 221 | // 这里刻意**不**断言严格相等 —— 否则并行窗口里别人的提交(或本单元第二提交)会把本判据判红。 |
219 | 222 | expect(TOTAL, `实测总数 ${TOTAL} 已超过冻结 ${FROZEN_LOADING_TEXT_TOTAL}(迁移后请把基线一起收紧)`).toBeLessThanOrEqual( |
220 | 223 | FROZEN_LOADING_TEXT_TOTAL, |
221 | 224 | ); |
222 | | - for (const f of MIGRATED_FILES) { |
223 | | - expect(FROZEN_LOADING_TEXT_BY_FILE[f], `${f} 在迁移面里,上限必须是 0`).toBe(0); |
224 | | - } |
| 225 | + // ★ 表的**每一格**都被两张声明表钉死(T13–T15 评审 M-1 的洞:原来只钉迁移面 ⇒「总数 + 某个残留格 |
| 226 | + // 同时 +1」全绿)。三种 kind 的允许残留数一律是 1 处/文件(见 loadingBaseline 的键语义:0=已承载)。 |
| 227 | + const expected: Record<string, number> = {}; |
| 228 | + for (const f of MIGRATED_FILES) expected[f] = 0; |
| 229 | + for (const r of RESIDUAL) expected[r.file] = 1; |
| 230 | + expect(FROZEN_LOADING_TEXT_BY_FILE, "冻结表 ≠ 迁移面(0) ∪ 残留面(1):多余键 / 漏键 / 某格上限被手改").toEqual(expected); |
| 231 | + expect(FROZEN_LOADING_TEXT_TOTAL, "冻结总数 ≠ 残留条目数(残留面每条恰 1 处 ⇒ 两者必须相等)").toBe(RESIDUAL.length); |
225 | 232 | }); |
226 | 233 |
|
227 | 234 | it("④ 残留声明自洽:每条带合法分类与非空理由,且声明键集 == 冻结表里值 > 0 的键集", () => { |
|
0 commit comments