起因:`node run-all.mjs` 报 `verdict=red` 但四个计数全是 0 ——
红来自**到期闸**(`dueFailed`)与**计数棘轮**,不是断言失败。
逐个查清,三处都做成了真问题并留证。
## ① 跨文件手写色清册的正则从 `{6}` 放宽到 6 或 8 位
`glassCard` / `glassCardWall` 是 **8 位**(`#EBFFFFFF` / `#C7FFFFFF`,
半透明白是 WebUI `.glass-card` 的本质),而那条判据的正则只认 6 位 ⇒
它看不见这两个令牌,却报出「清册里的 glassCard 已不存在(清册过期)」——
**病因报错了**:不是清册过期,是正则比被判的东西窄。
改成 `{6}(?:[0-9A-Fa-f]{2})?`。★ 不能写 `{6,8}`:那会把 7 位这种非法长度也放进来。
同一形状在另两条判据上各出现一次(`B|旧机制不得回来` 与
`遮罩:交给系统的遮罩语义色`),它们原来**全仓**扫 `#……{8}` ⇒ 把这两个
**不是遮罩**的令牌一起撞红。都改成**同名枚举白名单**(不是放宽:
遮罩那个真实约束原样保留 —— `overlay` 写成 8 位单色照样红)。
## ② 变异锚点过期(守具有齿但没挂上)
`jobs/jobs-all.json` 里「写死色值 + 去卡片圆角」那条的锚点,
被 `6ca0113` 插进去的 `.attributeModifier(PressEffectModifier.of())` 隔断 ⇒
`hits=0`、`skipped=1`,而**没有任何东西变红**。
已把锚点补成当前代码形状,`ran` 从 51 回到 52、`skipped=0`。
★ 这是本仓那个老形状的又一次实例:**"清单没跟上代码"不会自己报警**,
得靠 `hits=0` 那条判据;它本次确实报出来了(`diag=mutant-anchor-stale`)。
## ③ 计数棘轮 6 → 7
给 `cross-client-logic` 新增了 `AddressSuggest` 一组(地址补全纯逻辑),
而套件只判**下界** ⇒ 不同步这个数字,将来**删掉**那一组不会有任何东西变红。
已显式改成 7,并写清"为什么必须手改"。
## ④ baseline 第 10 次重算(先证不是残留才重算)
`AdminUsersPage.ets` / `SettingsPage.ets` 哈希对不上,逐个取证:
- `sha256sum -c` → 这 2 个 FAILED(另 5 个 OK)
- `git diff --quiet HEAD` → **空**(与 HEAD 逐字节相同)⇒ 底本**过期**,不是残留
- `git log --oneline -3` → 最后一次动它们是 `f83c233`(我上一批的有意编辑)
★ 值得记一笔:漂移的是**上一轮**的文件,我这一轮完全没碰它们。
若只按"`git diff HEAD` 空就放行",这条**永远发现不了自己漏了一次重算** ——
这次是靠 `summary.py` 的 `baseline-stale` 主动报出来的。
## 结果
`files=34 ran=34 checks=543 pass=542 fail=0 skip=1 red=0 broken=0`
`mutants=52 ran=52 skipped=0 diag=none baseline=7/7✓`
(`verdict=red` 仅剩到期闸:5 条"只能静态"的判据,其到期前提"能装能点设备"
现已成立,需要各自升级成行为判据 —— 已登记,不由这条提交关闭。)
233 lines
8.4 KiB
JSON
233 lines
8.4 KiB
JSON
[
|
||
{
|
||
"file": "client/harmony/entry/src/main/ets/model/AdminUsers.ts",
|
||
"pat": "return role === 'admin';",
|
||
"repl": "return role !== undefined && role.trim().toLowerCase() === 'admin';",
|
||
"test": "admin",
|
||
"why": "角色判定放宽"
|
||
},
|
||
{
|
||
"file": "client/harmony/entry/src/main/ets/model/AdminUsers.ts",
|
||
"pat": " if \\(!found\\) \\{\n out\\.push\\(item\\);\n \\}\n return out;",
|
||
"repl": " if (!found) {\n list.push(item);\n }\n return list;",
|
||
"test": "admin",
|
||
"why": "toggled 就地改入参"
|
||
},
|
||
{
|
||
"file": "client/harmony/entry/src/main/ets/model/AdminUsers.ts",
|
||
"pat": "if \\(v === undefined \\|\\| v\\.length === 0\\) \\{",
|
||
"repl": "if (v === undefined) {",
|
||
"test": "admin",
|
||
"why": "空串不当从未登录"
|
||
},
|
||
{
|
||
"file": "client/harmony/entry/src/main/ets/model/AdminUsers.ts",
|
||
"pat": " if \\(user\\.role === 'admin'\\) \\{\n return false;\n \\}\n",
|
||
"repl": "",
|
||
"test": "admin",
|
||
"why": "管理员也打受限徽标"
|
||
},
|
||
{
|
||
"file": "client/harmony/entry/src/main/ets/model/AdminUsers.ts",
|
||
"pat": "return '操作失败(服务端没有给原因)';",
|
||
"repl": "return '操作失败';",
|
||
"test": "admin",
|
||
"why": "兜底句不说原因缺席"
|
||
},
|
||
{
|
||
"file": "client/harmony/entry/src/main/ets/model/AdminUsers.ts",
|
||
"pat": " return message;\n \\}\n if \\(!isApiError",
|
||
"repl": " return '操作失败';\n }\n if (!isApiError",
|
||
"test": "admin",
|
||
"why": "吞掉服务端文案"
|
||
},
|
||
{
|
||
"file": "client/harmony/entry/src/main/ets/model/ImagePrep.ts",
|
||
"pat": "const longest: number = Math\\.max\\(width, height\\);",
|
||
"repl": "const longest: number = width;",
|
||
"test": "prep",
|
||
"why": "缩放按宽算"
|
||
},
|
||
{
|
||
"file": "client/harmony/entry/src/main/ets/model/ImagePrep.ts",
|
||
"pat": "const scale: number = Math\\.min\\(1, maxEdge / longest\\);",
|
||
"repl": "const scale: number = maxEdge / longest;",
|
||
"test": "prep",
|
||
"why": "小图被放大"
|
||
},
|
||
{
|
||
"file": "client/harmony/entry/src/main/ets/model/ImagePrep.ts",
|
||
"pat": "second\\.maxEdge = RETRY_EDGE;",
|
||
"repl": "second.maxEdge = MAX_EDGE;",
|
||
"test": "prep",
|
||
"why": "退档不降分辨率"
|
||
},
|
||
{
|
||
"file": "client/harmony/entry/src/main/ets/model/ImagePrep.ts",
|
||
"pat": "second\\.quality = RETRY_QUALITY;",
|
||
"repl": "second.quality = FIRST_QUALITY;",
|
||
"test": "prep",
|
||
"why": "退档不降质量"
|
||
},
|
||
{
|
||
"file": "client/harmony/entry/src/main/ets/model/ImagePrep.ts",
|
||
"pat": "return actualBytes > MAX_UPLOAD_BYTES;",
|
||
"repl": "return actualBytes >= MAX_UPLOAD_BYTES;",
|
||
"test": "prep",
|
||
"why": "等于上限也退档"
|
||
},
|
||
{
|
||
"file": "client/harmony/entry/src/main/ets/model/ImagePrep.ts",
|
||
"pat": "if \\(sizeBytes > MAX_SOURCE_BYTES\\) \\{",
|
||
"repl": "if (sizeBytes >= MAX_SOURCE_BYTES) {",
|
||
"test": "prep",
|
||
"why": "边界 >= 而不是 >"
|
||
},
|
||
{
|
||
"file": "client/harmony/entry/src/main/ets/model/ImagePrep.ts",
|
||
"pat": "if \\(!mimeType\\.startsWith\\('image/'\\)\\) \\{",
|
||
"repl": "if (false) {",
|
||
"test": "prep",
|
||
"why": "不判类型"
|
||
},
|
||
{
|
||
"file": "client/harmony/entry/src/main/ets/model/ImagePrep.ts",
|
||
"pat": "return '上传失败:' \\+ serverMessage;",
|
||
"repl": "return '上传失败';",
|
||
"test": "prep",
|
||
"why": "吞掉上传失败文案"
|
||
},
|
||
{
|
||
"file": "client/harmony/entry/src/main/ets/model/ImagePrep.ts",
|
||
"pat": "export const MAX_UPLOAD_BYTES: number = 3_670_016;",
|
||
"repl": "export const MAX_UPLOAD_BYTES: number = 6_291_456;",
|
||
"test": "prep",
|
||
"why": "上限超过服务端 4MiB"
|
||
},
|
||
{
|
||
"file": "client/harmony/entry/src/main/ets/model/ImagePrep.ts",
|
||
"pat": "export const MAX_EDGE: number = 2560;",
|
||
"repl": "export const MAX_EDGE: number = 4096;",
|
||
"test": "prep",
|
||
"why": "首档最长边改 4096"
|
||
},
|
||
{
|
||
"file": "client/harmony/entry/src/main/ets/pages/AdminUsersPage.ets",
|
||
"pat": " if \\(isRestricted\\(user\\)\\) \\{",
|
||
"repl": " if (false) {",
|
||
"test": "admin",
|
||
"why": "去掉受限徽标"
|
||
},
|
||
{
|
||
"file": "client/harmony/entry/src/main/ets/pages/AdminUsersPage.ets",
|
||
"pat": " onlyStatus\\.status = 'active';",
|
||
"repl": " onlyStatus.status = 'active';\n onlyStatus.display_name = this.editDisplayName;",
|
||
"test": "admin",
|
||
"why": "启停顺带发 display_name"
|
||
},
|
||
{
|
||
"file": "client/harmony/entry/src/main/ets/pages/AdminUsersPage.ets",
|
||
"pat": " \\.backgroundColor\\(Theme\\.surface\\)\\n \\.borderRadius\\(Theme\\.radiusCard\\)\\n \\.attributeModifier\\(PressEffectModifier\\.of\\(\\)\\)\\n \\.onClick\\(\\(\\) => \\{ this\\.toggleEdit\\(user\\); \\}\\)",
|
||
"repl": " .backgroundColor('#123456')\n .attributeModifier(PressEffectModifier.of())\n .onClick(() => { this.toggleEdit(user); })",
|
||
"test": "admin",
|
||
"why": "写死色值 + 去卡片圆角"
|
||
},
|
||
{
|
||
"file": "client/harmony/entry/src/main/ets/pages/SettingsPage.ets",
|
||
"pat": " this\\.isAdmin = false;\n \\}",
|
||
"repl": " this.isAdmin = true;\n }",
|
||
"test": "admin",
|
||
"why": "身份读不到时乐观显示入口"
|
||
},
|
||
{
|
||
"file": "client/harmony/entry/src/main/ets/pages/SettingsPage.ets",
|
||
"pat": " if \\(this\\.isAdmin\\) \\{",
|
||
"repl": " if (true) {",
|
||
"test": "admin",
|
||
"why": "管理入口不做门禁"
|
||
},
|
||
{
|
||
"file": "client/harmony/entry/src/main/ets/pages/SettingsPage.ets",
|
||
"pat": " @State isAdmin: boolean = false;",
|
||
"repl": " @State isAdmin: boolean = true;",
|
||
"test": "admin",
|
||
"why": "isAdmin 初值 true"
|
||
},
|
||
{
|
||
"file": "client/harmony/entry/src/main/ets/common/BackgroundPicker.ets",
|
||
"pat": "if \\(!overLimit\\) \\{\n\\s*break;",
|
||
"repl": "if (true) {\n break;",
|
||
"test": "prep",
|
||
"why": "永远只压第一档"
|
||
},
|
||
{
|
||
"file": "client/harmony/entry/src/main/ets/common/BackgroundPicker.ets",
|
||
"pat": "if \\(packed === null \\|\\| overLimit\\)",
|
||
"repl": "if (packed === null)",
|
||
"test": "prep",
|
||
"why": "两档都超限不拒绝"
|
||
},
|
||
{
|
||
"file": "client/harmony/entry/src/main/ets/common/BackgroundPicker.ets",
|
||
"pat": "overLimit = shouldRetryWithActual\\(usedBytes\\);",
|
||
"repl": "overLimit = false;",
|
||
"test": "prep",
|
||
"why": "结论恒 false"
|
||
},
|
||
{
|
||
"file": "client/harmony/entry/src/main/ets/common/BackgroundPicker.ets",
|
||
"pat": "await packer\\.release\\(\\);",
|
||
"repl": "packer.release();",
|
||
"test": "prep",
|
||
"why": "packer.release 不 await"
|
||
},
|
||
{
|
||
"file": "client/harmony/entry/src/main/ets/common/BackgroundPicker.ets",
|
||
"pat": "await head\\.release\\(\\);",
|
||
"repl": "head.release();",
|
||
"test": "prep",
|
||
"why": "head.release 不 await"
|
||
},
|
||
{
|
||
"file": "client/harmony/entry/src/main/ets/common/BackgroundPicker.ets",
|
||
"pat": "desiredSize: \\{ width: size\\.width, height: size\\.height \\}",
|
||
"repl": "desiredSize: { width: info.size.width, height: info.size.height }",
|
||
"test": "prep",
|
||
"why": "按原图尺寸解码"
|
||
},
|
||
{
|
||
"file": "client/harmony/entry/src/main/ets/common/BackgroundPicker.ets",
|
||
"pat": " quality: Math\\.round\\(quality \\* 100\\)",
|
||
"repl": " quality: quality",
|
||
"test": "prep",
|
||
"why": "quality 不换算"
|
||
},
|
||
{
|
||
"file": "client/harmony/entry/src/main/ets/common/BackgroundPicker.ets",
|
||
"pat": " this\\.onUploaded\\(UPLOAD_OK_HINT\\);",
|
||
"repl": " this.bgKind = 'image';",
|
||
"test": "prep",
|
||
"why": "组件自己宣布成功"
|
||
},
|
||
{
|
||
"file": "client/harmony/entry/src/main/ets/api/ApiClient.ets",
|
||
"pat": "name: 'file',\n contentType: mimeType",
|
||
"repl": "name: 'image',",
|
||
"test": "prep",
|
||
"why": "multipart 字段名不是 file(uploadBytes 那一处;此前锚点命中 2 次跑不起来,已切片)"
|
||
},
|
||
{
|
||
"file": "client/harmony/entry/src/main/ets/api/AppearanceApi.ets",
|
||
"pat": "fileName, 'image/jpeg'\\);",
|
||
"repl": "fileName, 'application/octet-stream');",
|
||
"test": "prep",
|
||
"why": "上传 mime 发错"
|
||
},
|
||
{
|
||
"file": "client/harmony/entry/src/main/ets/pages/SettingsPage.ets",
|
||
"pat": " await store\\.syncFromServer\\(ctx, client\\);\n this\\.adoptSnapshot\\(store\\.current\\(\\), store\\.statusText\\(\\)\\);\n \\}\n\n /\\*\\* 把 store 里的快照复制进 @State",
|
||
"repl": " this.bgKind = 'image';\n }\n\n /** 把 store 里的快照复制进 @State",
|
||
"test": "prep",
|
||
"why": "上传成功后不重新同步"
|
||
}
|
||
] |