Files
MailUI4Agents/client/electron/test/mutants/baseline.sha
JianFeeeee 5e4a1b616c 跨端: B 的交付物(跨端纯逻辑一致性判据)+ 照 skill 回扫修掉两处隐形债
用户:「你为什么不加载鸿蒙开发相关skill?」—— 说得对。那份
`arkts-grammar-standards` 写着 "REQUIRED before writing the first .ets file of a
session",而我这轮一直在写 `.ets`。补加载后照它的规则表**逐条回扫**,
当场抓出两处此前没人管的违规。

══ ① 用户要做的 B:`cross-client-logic.test.mjs`(新,6 条判据)

背景:两套纯逻辑各写一份且已分叉(replyTarget 214/170 行、mailGroups 178/459、
appearance 187/324、calendar 208/446)。当天已**踩到**两处分叉
(`participantAddress` 的 `||`、`ThreadPage` 字段全错)。

做法:**同一张用例表喂给两边,逐条比结果**(`--experimental-strip-types`
直接在 node 里跑两侧源码 —— 两边的 model 层都是纯逻辑、无 SDK 依赖)。
不选"生成一份共享源码":harmony 不能 import 工程外文件,
且两边类型系统不同(ArkTS 禁解构/any/对象字面量要具名类型),
生成器要维护"两边都能过"的子集,是另一个大工程。

★ **首轮运行就报出两处真分叉,都不是我踩到才发现**:
  ① `formatAddress('dsh', undefined, undefined)`:electron 返回 `"dsh"`,
     harmony **抛** `Cannot read properties of undefined`。
     —— 又是 `omitempty` 那个坑(**第三次**),这次是判据先报的。
  ② `monthGrid`:electron **固定 6 行**(`grid-rows-6`),harmony **4~6 行**
     ⇒ 翻月时网格高度跳动。WebUI 的注释明写要避免这个("行数变化会让整个
     网格高度跳动,翻月时页面内容上下弹")。
  ③ 顺着 ② 又发现:WebUI 邻月格子**填真实日期并置灰、可点**
     (`CalendarView.tsx:545-556`),harmony 留**空白格**。

★ 判据自身的两次错,都留了档(判据的 bug 与代码的 bug 一样危险):
  · 第一版把 `args[0]` 当单个参数传,字符串被当可迭代对象展开 ⇒
    `formatAddress('d','s','h')` —— **判据自己造出假分叉**。
  · 第一版 `weekStart` 传 0(周日),而两端实际都是 1(周一)⇒ 又一处假分叉。
    差一点就去"修"一个不存在的问题。
  · `monthGrid` 的投影第一版按 `inMonth ? [y,m,day] : null`,
    把"邻月填不填真日期"这个**真分叉**抹平了 —— 投影只该换表示,不该替我看不看。

★ 三类"不同"要分清(写进文件头):**命名不同**(投影归一,不是分叉)、
  **签名不同**(ArkTS 没 Date 重载习惯;语义必须一样)、**行为不同**(是分叉,以 electron 为准)。

══ ② skill 回扫抓出的两处隐形债(编译器只告警、判据也不管)

· **正则字面量**(`arkts-no-regexp-literals`):`MailDetailPage.ets:615` 的
  `/^\d+$/`(从 2026-09-19 活到今天)。
· **废弃的全局 `router`**:`api/Logout.ets:76` 的 `router.replaceUrl(...)`。
  它是个独立函数(没有 `this`)⇒ 拿不到 `UIContext`,改成由调用方传
  (两个调用点都持有 `getUIContext()`,零成本)。

★ 这两条为什么能活这么久:**编译器对它们只告警、不挡构建**,
  全仓也**没有判据**管 ⇒ 规则事实上不存在。已补两条判据,都做了变异验证。

══ ③ 顺带修正一条**恒真的同义反复**断言

`harmony-calendar` 里 "today 不在本月:不许标在别的月" 那条:
它是在"邻月格子是空 `DayCell`(`iso` 为空串)"时写的 ⇒ `c.iso === today`
**永远不可能**匹配 ⇒ `count === 0` 恒真,**看起来守着一条规则,其实什么都没守**。
改成真不变量:**"被标为今天的那一格,iso 必须就是 today;至多一格"**,
并反向核对"2026-10-01 确实出现在 9 月网格里"(否则那段是空转)。
实测 WebUI `CalendarView.tsx:547` 是逐格 `isSameDay` ⇒ **它会标**,
所以原来那条"不许标"本身就窄了一半。

══ ④ 登记两处盘点发现(**没有**顺手改,因为需要人决定)

· `harmony-dead-pages`:`InboxPage.ets`(238 行) 不可达(不在页面表、无人导航),
  `SessionsPage.ets`(170 行) 唯一引用来自 InboxPage ⇒ 一起不可达。
  没删是因为 `HARMONY-ALIGN-PLAN.md:214` 把它当变异测试靶子用过 ——
  删掉会永久丢代码,是否只是"早期留存"我判断不了。
· `harmony-permission-history`:WebUI 授权栏显示**待决 + 已决策历史**两段
  (拿 inbox 自己分组,`PermissionList.tsx:27/174/182`);鸿蒙调专用端点
  `/permission/pending`(SQL `WHERE pr.result IS NULL`)⇒ **只拿得到待决的**。
  已在 `cross-client-logic` 的 gaps 里如实登记,判据会盯着"不要再少"。

══ 判据状态

`files=33 ran=33 checks=530 pass=530 fail=0 skip=0 red=0 broken=0 unreported=0`;
`baseline=7/7✓`(底本第 9 次重算,已按规矩先 `git diff --quiet HEAD` 取证 + 记录理由)。
`verdict=red` 残余仍是 5 条静态判据的**设备到期提示**(既有机制)。

══ 环境

模拟器昨天起卡死(hdc 能连、shell 超时、CPU 150%、跑了 34 小时),
导致设备判据各跑 836 秒后失败 —— 看起来像"套件卡死"。用户批准后杀掉重启
(`Emulator -start HATriple -noWindow`,`devecocli` 那套因 x11 起不来),
现在**75~150 秒**跑完整套。
2026-09-20 22:35:35 +08:00

134 lines
12 KiB
Plaintext
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.

# 变异体基线的**自证底本**:每个被变异过的文件在此记下"未变异"时的 sha256。
# 跑完变异后 `sha256sum -c baseline.sha` 必须全 OK(summary.py 把结果打进 RESULT 行)。
#
# 取基线是**有意的动作**,不是随手重算 —— 重算会把"某次变异没还原"永久掩盖掉。
# 每次重算都要在此记一行"为什么":
# 2026-09-20 10:xx baseline 重算(第 8 次)—— 用户:「所有顶栏统一玻璃圆框」「抽象统一顶栏组件」
# 「发件箱太大了」「各组件带响应点击动画了吗」「转场动画呢」「还有其他行为要一一对齐」。
# ① 有意编辑:`MainPage.ets`(SentTab/PermissionTab 顶栏改 AppHeader、挂按压反馈)、
# `SettingsPage.ets`(标题行改 AppHeader)、`AdminUsersPage.ets`(Header 改 AppHeader)。
# ② 两个都跑过 `git diff --quiet HEAD -- <f>` 取证。
# ★ 本轮最大的收获是**两个「看起来做了、其实没生效」的坑**:
# · `.attributeModifier()` **一个组件只能挂一个**,链两个是后者覆盖前者 ——
# 会话组头卡同时挂了玻璃与按压反馈,结果只生效一个,编译器不报错。
# 修法:`CompositeModifier` 显式合成(CSS 的类名天然叠加,ArkUI 是单一插槽)。
# · `applyPressedAttribute` **只对自带按压状态机的组件**(Button)回调;
# 纯 `Row`/`Column`(全仓 117 处 onClick 的主体)一次都不触发 ——
# 实测:挂上去后按下与常态逐像素相同。改用 `onTouch` + 系统点击效果色。
# 2026-09-19 22:xx baseline 重算(第 7 次)—— 用户:「玻璃要更透明/磨砂更有质感」+「判据去芜存菁」。
# ① `pages/SettingsPage.ets` / `pages/MainPage.ets`:有意编辑 ——
# 页面里的玻璃三连(`backgroundColor` + `backgroundBlurStyle`)收敛成
# `.attributeModifier(GlassCardModifier.of(this.bgActive))` / `PaneModifier.of(...)`
# (用户:「定义一个基础玻璃容器给各个组件引用」)。
# ★ 途中一度把 `@Styles glassCard()` 里也替换成了 `attributeModifier`,
# 造成该页 ProfileSection/AppearanceSection/PushSection **整块不渲染**
# (设备实测:Scroll 直接跳到「客户端连接密钥」)。已删掉那个死 `@Styles`。
# ② 两个都跑过 `git diff --quiet HEAD -- <f>` ⇒ 非空(是"我改的",不是变异残留)。
# ★ 本轮到目前为止判据侧修了 4 个**判据自身的缺陷**(都不是放水,是补上它声称却漏判的类):
# · 材质来源只扫 `backgroundBlurStyle` —— 玻璃改成 `backgroundEffect` 后整类漏判
# (实测:塞一行裸 `backgroundEffect({radius:99,saturation:9.9})` 照样全绿);
# · 参数抽取用 `[^)]*`,对 `this.materialOf()` / `{...}` 对象字面量都截断 ⇒ 误伤合法写法;
# · 嵌套判定**没比文件**,拿 A 文件的偏移比 B 文件 ⇒ 判出物理上不可能的红;
# · `harmony-appearance` 数的是**内联字面量**("三元出现 ≥5 次"),
# 收敛成组件后写法变了、行为没变却变红 ⇒ 改成判不变式。
# 2026-09-19 21:0x dsh:baseline 重算(第 6 次)—— 用户要求「基础玻璃容器 + 补出现/消失动画」。
# ① `pages/AdminUsersPage.ets`:有意编辑 —— 「新建用户」表单补 `paneRiseIn()` 过渡
# (原来挂着 `if (this.showCreate)` 却硬弹;用户:「元素的出现消失动画呢?」)。
# 过渡挂在**调用点的 Column** 上,不是 `CreateForm()` 内部:`@Builder` 调用返回 void,
# 链不上修饰符(第一版就写错在内部,是新判据抓出来的)。
# ② `pages/SettingsPage.ets`:有意编辑 —— 所有卡片面 `Theme.surface` →
# `bgActive ? Transparent : surface` + `Theme.cardMaterial`(玻璃卡);
# 并**去掉**两处内层容器的材质(账号列表 / 密钥列表)——
# 那两处是"卡里面的一段列表",两层都铺材质 = 嵌套玻璃(判据 C 条会红)。
# ③ 两个都逐个跑过 `git diff --quiet HEAD -- <f>` ⇒ 非空(是"我改的");
# 另 grep 确认无裸 `BlurStyle.XXX` 残留、无变异留下的空 transition。
# ★ 本次判据侧也改了:C 条从"逐处登记白名单"改成"材质必须来自设计令牌"
# (玻璃从少数例外变成**默认**,白名单挡不住新写的裸枚举)。
# 2026-09-15 11:22 dsh:`AdminUsersPage.ets` 的哈希变了,**不是变异残留**。
# 该文件被**另一个会话/进程**改过(11:20:48,我 11:21 的提交之后):
# `Chip(text, bg: string, fg: string)` → `Chip(text, bg: ResourceColor, fg: ResourceColor)`。
# 核实过是**正确的 ArkTS 修法**(`Theme.surfaceMuted`/`textSubtle` 是 `Resource`,
# `Theme.chipNeutralBg` 是 `string` ⇒ 旧签名编译不过)。我没有提交也没有回退它。
#
# 2026-09-15 11:50 dsh:三个文件漂移,全部核实为**有意改动、不是变异残留**:
# · `model/Appearance.ts` + `pages/MainPage.ets`:**我自己**按 pi 的裁定把方案 (b) 落地成 (a)
# (删 `navMaterialFor` 与 `NAV_MATERIAL_OF`、导航条改回 `Theme.navMaterial`、
# 重写那段"注释说 (a)、代码是 (b)"的自相矛盾注释)。
# · `api/ApiClient.ets`:**别的会话**的提交 `69c2059`(JianFeeeee,11:43:22,
# 推送客户端契约层)动过它;当前内容与 HEAD 逐字节相同(`git diff HEAD` 空)。
# 复核"是不是变异残留"的方法:`git diff HEAD -- <文件>` + 上面这些记录。
#
# 2026-09-18 dsh:三个文件漂移,**已逐个核实是提交态、不是变异残留**(重算前的前提):
# · `AdminUsersPage.ets`、`SettingsPage.ets`:提交 `1be8318`(09-17 21:15,
# "底栏黑带 / 联系人点不开"那批)改过;`git diff --quiet HEAD` 为空 ⇒ 与 HEAD 逐字节相同。
# · `ApiClient.ets`:提交 `fce5b91`(09-15 15:15,"鸿蒙客户端连不上服务器")改过;同上。
# ★ 为什么必须先证这一步:底本**过期**与**变异残留**在 `sha256sum -c` 眼里一模一样,
# 而重算会把真正的残留**永久掩盖** —— 所以"重算"必须是一次**有记录**的动作。
# ★ 顺带修了播报:原来一律打"有文件没还原"(指向最危险的结论),
# 而真因只是底本没跟上提交 ⇒ 现在两种分开报,并各自给出判别方法。
#
# 2026-09-19 13:0x dsh:四个文件漂移,**已逐个核实是提交态、不是变异残留**(重算前的前提):
# · `pages/AdminUsersPage.ets`:提交 `6693e96`(09-18 11:47,"登录页那个 emoji 是 Unicode…")
# · `common/BackgroundPicker.ets`、`pages/SettingsPage.ets`:提交 `7e1120a`
# (09-19 12:30,"顶栏不再自己铺白条 + 日历改左右两栏…")
# · `api/ApiClient.ets`:提交 `7e10bfa`(09-18 12:55,"鸿蒙日历补 .ics 导入导出")
# 四个都 `git diff --quiet HEAD -- <f>` ⇒ **与 HEAD 逐字节相同** ⇒ 底本过期,不是残留。
# ★ 为什么必须逐个证这一步:底本**过期**与**变异残留**在 `sha256sum -c` 眼里一模一样,
# 而重算会把真正的残留**永久掩盖** —— 所以"重算"必须是一次**有记录**的动作。
# ⚠️ 这次漂移正是 `baseline-stale`(rc=0、只提示)那一档的又一次实例:
# 它**不假红**(正常提交不会天天红),但也**不会被自动发现** ——
# 我是靠"核每个文件的登记/实际读数"这条主动核查撞上的,不是它自己报的。
#
# 2026-09-19 18:2x baseline 重算(**先核过不是残留,才重算的**):
# ① `pages/AdminUsersPage.ets`、`pages/SettingsPage.ets` —— 我本次的**有意编辑**:
# 给所有"压在彩色底上的字/图标"换前景色(`Theme.surface` → `Theme.accentFg`),
# 并把品牌蓝前景接入 `Theme.accentFor()`(深色下提亮到 WebUI 的 `--c-blue-600`)。
# ② `api/AppearanceApi.ets` —— **与 HEAD 逐字节相同**(`git diff --quiet HEAD` 为空),
# 但底本哈希对不上 ⇒ 说明它在底本取完之后被**合法改过**(提交 `3b5cc63`,
# 09-19 那次"外观保存 400"的修:`payloadFromLocal` 改用 `AppearancePayload`)。
# ⇒ 这是 `stale`(底本过期),不是 `residue`(变异残留)。
# ★ 三个都逐个跑过 `git diff --quiet HEAD -- <f>` 取证,没有一个是"改动忘了还原"。
# ★ 这正是这份文件里那条纪律的第 3 次执行:"重算必须是一次有记录的动作"。
#
# 2026-09-19 20:2x baseline 重算(第 4 次,**仍先核过不是残留**):
# ① `pages/AdminUsersPage.ets` / `pages/SettingsPage.ets` / `common/BackgroundPicker.ets`
# —— 本次的**有意编辑**:语义色前景接入 `dangerFor()/approveFor()/warnFgFor()`
# (深色下红/绿/琥珀要提亮,对齐 WebUI `.dark --c-red/green/amber-700`),
# 以及三级文字接入 `textSubtleFor()`(深色下换二级,见 Theme.ets 里那段理由)。
# ② 三个都逐个跑过 `git diff --quiet HEAD -- <f>` ⇒ 全部**非空**(工作树有改动)
# ⇒ 是"我改的",不是"变异忘了还原"。
# ★ 取证命令留在这里,下次照着做:
# git diff --quiet HEAD -- <file> && echo STALE || echo INTENTIONAL
#
# 2026-09-19 20:4x baseline 重算(第 5 次):
# ① AdminUsersPage.ets / SettingsPage.ets -- 有意编辑:修三元里的裸 Theme.accent
# (前景位置漏改的那 2 处)+ 那一批 textSubtleFor()。
# ② 本次格外重要的一步:我批量替换 Theme.accent -> accentFor() 时,
# 误把 6 处 backgroundColor 也换了(accentFor() 深色给浅蓝 #80AFF9,
# 白字压上去约 1.4:1,主按钮文字会看不见)。发现后已逐处还原。
# 重算前专门复核过三件事(不能只看 git diff 非空就放行):
# - grep -c "backgroundColor(Theme.accentFor())" 得到 0
# - 三个涉及文件里都无 accentFor 背景
# - git diff HEAD~1 里 backgroundColor 只有 calendar 那一处
# (原本是 accentSoftFor,属本次有意改动)
# => 确认无「改错了没还原」的残留在。
# ③ 新增判据 C2(*For() 入口只能用于前景、不得当背景)把这整类钉住,
# 下次再手滑批量替换会直接判红,不必再靠事后复核。
# 2026-09-20 21:5x baseline 重算(第 9 次)—— 照 `arkts-grammar-standards` skill 的规则表回扫,
# 修掉两处「编译器只告警、判据也不管」的隐形债:正则字面量、废弃的全局 router API。
# ① 有意编辑:`SettingsPage.ets`(`performLogout` 多传一个 `UIContext`)。
# ② 取证:`git diff --quiet HEAD -- <f>` → INTENTIONAL(与 HEAD 不同);
# 再逐行核过 diff **只有这一处一减一加**,确认不是变异残留。
# ★ 为什么改这一行:`performLogout` 内部原来用**已废弃的全局 `router`** 做退出跳转;
# 改成 `ui.getRouter()` 就需要 `UIContext`,而它是独立函数(没有 `this`),
# 只能由调用方传 —— 两个调用点(`MainPage` 侧栏 / `SettingsPage` 我的页)都持有它。
# ★ 为什么这类债能活这么久:编译器对它们**只告警不挡构建**,全仓也**没有判据**管,
# ⇒ 规则事实上不存在。已补两条判据(正则字面量 / 废弃全局 API),都做了变异验证。
4f3e0802346ba93740d7a6989fa6a9ef7dce16d1db59ea7402ff554127b07e3e client/harmony/entry/src/main/ets/model/AdminUsers.ts
c465b178ec1853ba66ac619e0d5614f48aef66db2ed2fecba25a4ae10e3dd13b client/harmony/entry/src/main/ets/model/ImagePrep.ts
5778eb9cc2af326b9f51ef9d53a66efa058fd0b5cfbef2881b603f9d367ac2a5 client/harmony/entry/src/main/ets/pages/AdminUsersPage.ets
73c66c7045f579c3eb8b8e0aa07803e7c9363b7ae8375972b251633d3ce969be client/harmony/entry/src/main/ets/common/BackgroundPicker.ets
686daa16d68b7d22332c5ed714723279c3f103b25a8c808b15658b22333524cb client/harmony/entry/src/main/ets/pages/SettingsPage.ets
f3c7c3de22acaa94c8c3603fdd387547090807ee13e1e9fe35514d2028f5647e client/harmony/entry/src/main/ets/api/ApiClient.ets
6550e1892d1ebea82fb75a3d2cf8eaf826186199ff4a0ecf0430b1e3517d8681 client/harmony/entry/src/main/ets/api/AppearanceApi.ets