Files
MailUI4Agents/client/electron/test/mutants/jobs/jobs-all.json
JianFeeeee efb1c1d2ca 修复: 第四个落点 —— **变异条目的锚点失效**(hits=0):守具有齿,却不在位
pi `6aa2b17f` 报的第三例(`unlisted`/`ghosts` 退 0)**我复核后已经在 `6ee9902` 修好了**
—— 而它的**父提交正是 pi 报信时读的 `4b841e0`**(差 11 分钟)。又是同一形状的竞态。

但顺着同一条线**审计全部 61 个变异条目的锚点**,发现**还有一个同形状的落点,
而且它在真树上是活的**(不是构造的):

    hits=0  SettingsPage.ets 「管理入口不做门禁」(jobs-all.json)

根因:该锚点写的是 **6 空格**,而 `c523c21`(09-17 17:43)把该文件**重排成 4 空格**
⇒ 锚点从此命中 0 次(写进清单时 `bcd4f97`(09-15)它是**对的**)。

为什么没人发现:`summary.py` 把「hits=0 … 过期条目」**只打印**、**不进严重度链**
⇒ `rc=0`、`diag=none` ⇒ 套件 `whyLines: (note || status!==0) ? … : []` 为假 ⇒
**整段丢掉**。端到端实测(真树、干净工作树):套件输出里 grep「过期条目」= **0 次**。

★ 危害是"**一个变异守具被静默关掉**",不是"数字错了":`ran` 少 1、`skipped=1`
是个**中性数字**,读者看不出少了哪一个。而**手工施加那个变异仍能让判据红**
(`harmony-admin.test.mjs` `# fail 1`)⇒ **有齿,只是没挂上**。

修法(沿用 `summary.py` 的**唯一严重度链**):
  · 新增 `mutant-anchor-stale` ⇒ **1 档**(清单/数据该改;**不是** 2 档 ——
    照 `env-defaults.sh:25` 的反方向:别让"清单没跟上"冒充环境)。
  · 修锚点 6→4 空格 ⇒ `ran` 47→48、`skipped` 1→0,守具重新挂上(实测变异能红)。
  · `whyLines` 过滤器加 `^\s*hits=`:只说"有锚点过期"不够,**点名的才是可行动的**。
  · 两张表都登记(`UPSTREAM_RC` + `DIAG`,`blocksGreen: true`)+ 真跑案例
    (迷你仓库里放一个不含锚点的同名文件 ⇒ `hits=0`)+ 读者侧具名案例。

★ 射程如实标出:判据只看 **`hits == 0`**,**不看 `hits == -1`**(文件打不开是另一回事,
且迷你夹具里目标文件本来就不在 ⇒ 算进来会造假红)。**`-1` 那一半无判据守着**(真树 0 条)。

变异验证(4 个方向全抓):
  ① 新档关闭(回到"只打印")⇒ exitcode-selftest rc=1、2 条红 ✓
  ② 从 UPSTREAM_RC 删掉新码 ⇒ 反向覆盖点名 ✓
  ③ blocksGreen true→false ⇒ 双向口径漂移红 ✓
  ④ 放宽成任何 skipped_detail(含 hits=-1)⇒ rc=1、**5 条红**(夹具假红)
     ⇒ **`h == 0` 这个射程是承重的** ✓

端到端 A/B(隔离 worktree,同刻对照):
  A 锚点已修  ⇒ rc=0、diag=none、ran=48/skipped=0、"锚点已失效" grep **0**
  B 锚点退 6 格 ⇒ rc=1、diag=mutant-anchor-stale、ran=47/skipped=1、grep **2**

★ 通用规则(本仓第 4 次同一形状):**"跑了多少个"与"该跑多少个"之间也要有判据。**
被跳过时 `ran` 只少 1、`skipped` 只多 1 —— 都是中性数字,而"少了哪一个"没有通道。
凡"登记一批东西、再逐个挂上"的结构(变异条目、判据、样本表)都要问:
**挂不上的那一个,谁来说?**

自检 5 个各 rc=0;全套 checks=516 pass=511 fail=5 red=5 verdict=red;
mutants=48 ran=48 skipped=0 on_new_criteria=36 diag=none baseline=7/7✓。
CRITERIA.md §16.1.1 记这一笔(含 4 个变异与 A/B 表)。
2026-09-20 04:49:50 +08:00

234 lines
7.9 KiB
JSON
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

[
{
"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 \\.onClick\\(\\(\\) => \\{ this\\.toggleEdit\\(user\\); \\}\\)",
"repl": " .backgroundColor('#123456')\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": "上传成功后不重新同步"
}
]