From a7896a7e3a2f2b8406a7836a30a3a372f83d2e67 Mon Sep 17 00:00:00 2001 From: JianFeeeee Date: Sun, 20 Sep 2026 05:45:42 +0800 Subject: [PATCH] =?UTF-8?q?=E6=96=87=E6=A1=A3:=20CRITERIA.md=20=C2=A716.1.?= =?UTF-8?q?3=20=E2=80=94=E2=80=94=20=E5=88=A4=E6=8D=AE=E9=94=9A=E5=9C=A8"?= =?UTF-8?q?=E5=AD=97=E9=9D=A2=E7=9B=B8=E9=82=BB"=E9=9A=90=E5=90=AB?= =?UTF-8?q?=E6=96=AD=E8=A8=80"=E4=B8=8D=E8=AE=B8=E5=86=8D=E5=A4=9A?= =?UTF-8?q?=E4=B8=80=E5=B1=82"=EF=BC=88=E5=81=87=E7=BA=A2=E7=9A=84?= =?UTF-8?q?=E6=9D=A5=E6=BA=90=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 记 pi `7d98245a` §三 报的那条假红(`Motion.dur(...)` 包一层 ⇒ `duration:\s*Theme\.durRise` 失配),连同我自己量到的两半: · 无障碍层**零判据**:`isAnimationReduceEnabled`/`Motion.dur`/`Motion.reduced` 在 test/ 里 grep 各 0 次;WebUI 侧**有**(animation-audit.test.mjs:112)。 变异(`Motion.dur` 恒 return want)⇒ 失败集合逐条相同 ⇒ **零反应**。 · ★ 绕过面比"都包了"更大:**11 个真动画时长站点里 5 个绕过开关** (CalendarPage:373,410 / MainPage:2607,2845,2884 裸 `Theme.durX`) ⇒ "收成一个入口"的设计意图**只落了一半**。 通用纪律:**判据锚在"字面相邻"时,它其实断言了"两层之间不许再有一层"** —— 而那个隐含断言几乎从不是作者本意(本意是"这个令牌要被引用")。 二者在实现多一层合法卷绕(包装函数/无障碍开关/单位换算/类型转换)时**必然分叉**, 方向是**假红**。 ⇒ 与 §16.1.2 合成一条:**判据的严格度必须与它真正想守的那件事对齐, 而不是与"当时那版实现的写法"对齐。** --- client/electron/test/CRITERIA.md | 67 ++++++++++++++++++++++++++++++++ 1 file changed, 67 insertions(+) diff --git a/client/electron/test/CRITERIA.md b/client/electron/test/CRITERIA.md index 5642c4e..df6fdc6 100644 --- a/client/electron/test/CRITERIA.md +++ b/client/electron/test/CRITERIA.md @@ -1054,6 +1054,73 @@ hook / CI / cron 调用它。**而它当时正红着**: > 本仓 `stripComments` 自己那段注释早警告过"判据开始消费散文", > 但警告的是**字符串**,**没覆盖"另一种语言的注释"** —— 这一格是那个洞的实例。 +#### 16.1.3 ★★ 第六个落点:**判据锚在"字面相邻",而实现合法地多了一层**(pi 报 + dsh 复现,2026-09-20) + +`harmony-nav.test.mjs:441` 断言: + +```js +assert.match(body, /duration:\s*Theme\.durRise/, '★ paneRiseIn 里入场时长必须引用 Theme.durRise') +``` + +它要防的**真 bug** 是 2026-09-18 那笔:把"壁纸淡入的时长"(`durBase`) 当成"面板入场的时长"。 +**动机完全正确。** 但它的形状是"`duration:` 与 `Theme.durRise` **字面相邻**"。 + +而无障碍动效开关落地后,`Theme.paneRiseIn()` 合法地变成: + +```ets +).animation({ duration: Motion.dur(Theme.durRise), curve: Theme.easeRise }) +``` + +`Motion.dur(x) = reduced() ? 0 : x`(系统开"减少动效"就折成 0ms)。 +⇒ **语义上 `durRise` 仍被引用**,只是多了一层卷绕 ⇒ 正则失配 ⇒ **假红**。 + +**实测**(dsh,隔离 worktree,同刻对照): + +| 树 | `harmony-nav` | +|---|---| +| A 干净 HEAD | 19 tests / **18 pass / 1 fail**(`not ok 16`,设备条) | +| B HEAD + 未提交的无障碍改动 | **17 pass / 2 fail**(多出来的正是 `not ok 8`) | + +**修法**(放宽**包装**,不放宽**令牌**): + +```js +/duration:\s*(?:Motion\.dur\()?Theme\.durRise/ +``` + +★ **区分力实测未动**(3 个方向): + +| 变异 | 结果 | +|---|---| +| `Motion.dur(Theme.durBase)`(换令牌) | 仍红 ✓ | +| 裸 `Theme.durBase`(不包了,直接换) | 仍红 ✓ | +| 干净 HEAD 形状但换令牌 | 仍红 ✓ | + +且**下面那条 `!/Theme\.durBase/` 逐字仍在**、扫的是**整个函数体** +⇒ `Motion.dur(Theme.durBase)` 这种"包一层蒙混"**照样红**。 +修后全套 `red 5 → 4`(`harmony-nav` 从红名单出去,其余 4 条红是别的会话的)。 + +★★ **同一次量出的更值钱一条:那个无障碍层本身"零判据",而且只落了一半** + +- `client/electron/test/` 里 `isAnimationReduceEnabled` / `Motion.dur` / `Motion.reduced` + grep **各 0 次**;对照 **WebUI 侧有**判据(`animation-audit.test.mjs:112` 的 + `prefers-reduced-motion` 覆盖 `.rise-in`)。**同一份无障碍义务,Web 侧有守、鸿蒙侧没有。** +- **变异零反应**(dsh 复现 pi 的):把 `Motion.dur` 改成恒 `return want` + (整个开关失效,源里 6 处受影响)⇒ `harmony-nav` 失败集合与变异前**逐条相同**(`17/2`)。 +- ★ 而**绕过面比"6 处都包了"更大**:11 个真·动画时长站点里 **5 个绕过开关** —— + `CalendarPage.ets:373,410`、`MainPage.ets:2607,2845,2884` 是裸 `Theme.durX`。 + 即"**收成一个入口,漏掉的人写不出忘了判断的代码**"这个设计意图**目前只落了一半**。 + (另外 6 处:`Theme.ets` 5 处 + `Surface.ets:276`。) + +> **通用纪律(这一格的抽象):判据锚在"字面相邻"时,它其实断言了"两层之间不许再有一层"。** +> 那个隐含断言**几乎从来不是作者的本意** —— 作者本意是"**这个令牌要被引用**"。 +> 二者在实现多一层合法卷绕(包装函数、无障碍开关、单位换算、类型转换)时**必然分叉**, +> 而分叉的方向是**假红**。 +> ⇒ 写"源码里找写法"的判据时问一句:**我要的是"这两个字面上挨着",还是"这个令牌在这条链上"?** +> 若是后者,正则要给**卷绕**留位(`(?:Wrapper\()?`),而**"令牌"那一格一个字都不放**。 +> ★ 与 §16.1.2 同源:那一格是"判据读的语言不对",这一格是"判据读的形状比实现更死"。 +> 两次的教训合成一条:**判据的"严格度"必须与它真正想守的那件事对齐, +> 而不是与"当时那版实现的写法"对齐。** + ### 16.2 ★★ **同一优先级写了两遍 ⇒ 两个顺序**:不变式只在**对角线**上被验过(pi + dsh 2026-09-18) §16.1 讲"结论到不了决定颜色的那一格"。这一节是它的**镜像**: