Commit Graph

4 Commits

Author SHA1 Message Date
ff172ed2c1 判据: 修 AmIcon 尺寸检查的假红 —— 它跨过 } 吃到了下一个组件的修饰符
这条判据抓的是真形状(`AmIcon({…}).width(48)` 会让图标贴左上角),
但正则写宽了:`[\s\S]{0,200}?` 允许**跨过 `}`**,于是这种**正确**写法被判红:

    Row({ space: 4 }) {
      AmIcon({ … })
      Text('新建')
    }
    .height(26)      ← 这是 Row 的,不是 AmIcon 的

实测(日历工具栏新加的「+ 新建」按钮):报 `CalendarPage.ets:1223 → .height(`,
而那一行链在 `Row` 上。**是判据误报,不是代码错。**

修法:扫描区间**不允许出现 `{`/`}`**。`AmIcon({…}).width(48)` 里参数花括号已被
`)` 收尾,而跨到下一个组件的路径会被排除。

★ 修完**立刻做了变异验证**(这类放宽最容易顺手把判据改废):
   把真实的 `AmIcon({…})` 改成 `AmIcon({…}).width(48)` ⇒ **判红**;
   还原 ⇒ 绿。既要"不误报",也要"仍能抓真错",两半都得验。
2026-09-19 15:22:34 +08:00
0e5eec61bd 跨端: 登录页那个"emoji"是 Unicode 符号 —— 顺手修好图标贴左上角(共 4 处)
用户两条反馈,都是**看着界面**报出来的,而编译器与所有既有判据全绿:
①「为什么登陆页不是app图标,而是一个emojy?」
②「你自己看看那个图标的位置正常吗?」

## ① `Text('✉')` 被系统渲染成彩色 emoji

登录页的品牌标识原先写的是 `Text('✉')`(Unicode U+2709)。HarmonyOS 字体链里有
**彩色 emoji 字体**,U+2709 自带 emoji 字形 ⇒ 渲染成一枚黄白色风信封 emoji:

- `.fontColor(Theme.accent)` 对彩色 emoji **无效**(界面显示的是 emoji 自带颜色);
- 与底栏/侧栏那些 `AmIcon` 线描图标不是同一套视觉语言;
- 实测截图硬证:大屏下那枚 emoji 比旁边的文字还显眼。

而本仓**早就有** `ICON_PATHS.brandMark`(就是 App 图标上那个信封,专为品牌标识画的)。
换成 `AmIcon({ iconName: 'brandMark' })` 即可 —— 走 `Path.stroke()`,跟主题色走。

## ② 图标贴在卡片左上角(量出来的)

`AmIcon` 内部那个 `Stack` 是 `iconSize` 那么大、**默认靠左上**排版。调用方写
`AmIcon({…}).width(48).height(48)` 想要个大点的可上色盒子时,**外层盒子变大、图标不动**。

实测(三折叠 3.5 密度,`dumpLayout` 读的**实际 bounds**):

    卡片 [1523,521][1661,659]  138×138px
    图标 [1526,524][1589,587]   63×63px   ← 左边距/上边距都只有 3px
    ⇒ 图标中心偏 10vp

**不是一处**:全仓扫出 4 个同样写法。修法是套一层
`Stack({ alignContent: Alignment.Center })`(仓里回复球与悬浮加号本来就是这么写的,
所以它们一直是对的):

| 位置 | 图标 | 盒子 | 原状态 |
|---|---|---|---|
| 登录页品牌卡 | brandMark 24 | 48×48 | 贴左上 ✗ |
| 用户管理刷新键 | repeat 20 | 40×40 | 贴左上 ✗ |
| 联系人视图切换 | cardView 18 | 40×40 | 贴左上 ✗ |
| 收件箱组头箭头 | chevronRight 12 | 20 槽位 | 贴左 ✗ |
| 回复球 / 悬浮加号 | chatBubble / compose | 56×56 | 本来就对(尺寸在外层 Button 上) |

修后实测:偏移 **−34.5px → 0.5px**(0.14vp,亚像素级)。

## 判据(harmony-arkts 3 → 5 条)

- **图标不许用 Unicode 符号充当**:扫 `Text('…')` 里单个符号的情况。
  ★ 只框 U+2600–U+27BF / U+2B00–U+2BFF / U+FE0F,**刻意不含基本箭头段**(U+2190–U+21FF)——
  `→` 在正文里是标点不是图标,框进来会误伤大量正常文案。
  (我第一版把箭头段也框了,结果自检自己先红 —— 断言写错就是写错,不靠放宽它来「修」。)
- **尺寸不许直接链在 `AmIcon` 上**:把"图标贴左上角"这个坑的**形状**钉住,
  并自检"套了 `Stack` 的正确写法不许被误判"。

**两个变异方向都跑过**:放回 `Text('✉')` ⇒ 红 ✓;给 `AmIcon` 直接加 `.width(48)` ⇒ 红 ✓。
2026-09-18 11:47:51 +08:00
4af083e8b8 test(判据): 4 个判据读的是**另一棵树** —— 修掉硬编码的仓库根,并让 stripComments 保持行号
pi 2026-09-15 实测出来的,**这次长在判据自己身上** —— 正是我们前几轮一直在消的那个形状。

## 一、`const ROOT = '/home/program/agentmail'`:规则进来了,对象没进来

`harmony-arkts.test.mjs` 把仓库根写成了绝对路径。后果我按 pi 的步骤亲手复现了:

```
$ git worktree add --detach /tmp/wt-verify 7f4fa26      # 那个检出里 import 顺序**确实**违规
  (核对:最后 import 在第 80 行,而第 63 行已是 `const NAV_MATERIAL_OF…`)
$ cd /tmp/wt-verify/client/electron && node --test test/harmony-arkts.test.mjs
ok 1 / ok 2 / ok 3   # pass 3  # fail 0      ← **在一个明显违规的检出上 3/3 全绿**
```

因为它读的不是 `/tmp/wt-verify`,是 `/home/program/agentmail`(那份早已修好)。
两层后果,第二层最糟:
① 它**永远无法验证任何别的 checkout / CI / 镜像** —— 换目录不是"红",是 `readdirSync` 直接抛;
② 在本机做 worktree 复核时,它**静默读另一棵树并报绿**。
**判据的逻辑是对的、对象是错的** —— 这比"判据写错了"更难发现,因为它在原地永远是绿的。

同一个毛病在 4 个文件里,**恰好全是最近这几笔新写的**(另 10 个鸿蒙判据写法是对的):

```
harmony-admin / harmony-imageprep / harmony-presets / harmony-arkts  →  const ROOT = '/home/program/agentmail';
其余 10 个                                                          →  const ROOT = join(HERE, '..', '..', '..');
```

已全部照邻居改掉。**修好之后在同一个违规检出上:`# fail 1`** —— 它终于会红了。

## 二、修这条时又牵出一个:`stripComments` **改变了行号**

修好路径后,判据报出"最后一个 import 在第 64 行、第 47 行已是语句",
而**真实文件里是第 80 / 63 行**。成因:`stripComments` 把块注释整块抹成 `''`,
而块注释**自带换行** ⇒ 它之后所有行号整体前移。

这不是小节:全仓判据都用 `文件:行号` 定位(`grep -n`、编辑器跳转、`git show` 核对),
**报出来的行号必须能直接用**,否则读者第一步得先猜"这是剥过的还是没剥的"。
改成"块注释里的每个换行换成等量空行"。修完报的就是 **80 / 63**,与文件逐字对上。

## 三、新增两条判据,让这两个形状不能再回来

1. **`★ 判据不许把仓库根硬编码成绝对路径`** —— 扫判据目录里**真代码**
   (`code()` 剥注释,否则本文件自己的说明文字就会误报),找
   `const X = '/绝对路径'` 且**看着像仓库内**的声明。
   **例外按名字放行**(含 `TOOLCHAIN`/`SDK`/`HDC` 的常量)—— 工具链本来就不在仓库里、推不出来;
   按**值**做白名单会逼着下一个人为了过判据去改那个路径的写法。
2. **`★ stripComments 必须保持行号`** —— 造含多行块注释的样本,断言剥完
   **行数不变**、且第 N 行仍是原来的第 N 行;**同时**断言注释内容确实被去掉了
   (别为了保行号把注释留下)。

两条都做了**变异验证**:
- 把 `harmony-admin` 的 ROOT 改回硬编码 ⇒ 新判据**红**,并点名那个文件;还原后绿。
- 在 `MainPage.ets` **import 之前**插一条语句 ⇒ `harmony-arkts` **红**
  (第 79 行 vs 第 1 行);还原后绿。**这条同时证明了"读的是自己那棵树"** ——
  同样这个变异,在修路径**之前**是绿的。

## 四、未做 / 未验

- 到期闸门那 7 条**没动**(要真装真点,是另一件活)。
- **"把 build 做成一条判据"我探了,两个硬障碍**(详见给 pi 的回信):
  ① `client/harmony/oh_modules` 被 `.gitignore` 排除且未入库 ⇒ **全新检出没有它**,
     构建会先死在装依赖上;② 本沙箱**拒写 `/root/.hvigor`**(`mkdir` Permission denied),
     `hvigorw` 在 worktree 里直接 `EACCES: mkdir '/root/.hvigor/project_caches/…'`。
  所以它在本仓能编过、在干净检出编不过 —— 作为判据它现在会**假红**。
2026-09-15 12:06:15 +08:00
7f4fa2629e 跨端: ArkTS 编译期硬规则进判据 —— 我插的常量表把 import 挤到了后面,assembleHap 报 arkts-no-misplaced-imports
`hvigorw assembleHap` 在 `f31bc02`/`b806a05` 上都红了一条:

    ERROR: ArkTS:ERROR …/MainPage.ets
    "import" statements after other statements are not allowed  (arkts-no-misplaced-imports)

**是我造成的**:P4c 那笔我在 `MainPage.ets` 里插了 `NAV_MATERIAL_OF` 那张(带注释的)
常量表,位置在**既有 import 之前**。ArkTS 要求所有 import 在任何语句之前,
常量表算语句 —— 编译器直接报错。

## 为什么我那一笔的判据一条都没抓到它

因为**这个仓库里没有任何判据会跑 ArkTS 的编译规则**。我的判据判的是"表达式对不对、
接没接上、颜色写没写死…",它们全绿 —— **文本层面确实没问题**,问题只有编译器知道。
pi 是构建时撞上的。

⇒ 教训不是"下次小心",是**把编译器能抓、而判据不抓的那一类固化下来**。
这一类里有一批**纯文本就能判、不需要设备**,所以它们不该待在"等设备才能验"的欠账里。

## 做了什么

- 新增 `test/harmony-arkts.test.mjs`(3 条,不需要设备 ⇒ **不进** STATIC_ONLY):
  · **所有 26 个 `.ets` 的 import 必须在任何其它语句之前**(就是这次报的那条);
  · 全仓 `.ets` 的词汇层硬坑(对象解构 / `any` / `unknown` / 函数表达式)
    —— 这几条此前**只在"我自己新写的那个页面"里判**,而我恰恰是在**改既有文件**时犯的下一个错,
    编译期硬规则不该按"谁写的"分覆盖;
  · **一条自检**:造已知坏样本(常量插在两组 import 之间)确认检查会红、合法样本不误报
    —— 否则"全绿"可能只是扫描逻辑失效(我第一版就把多行 import 的成员行误判成了语句)。
- 接进 `SUITE`(判据文件数 22 → 23)。
- 文件头明确写了它**不能**替代 `hvigorw`:覆盖的只是"能静态判出来的那几类",
  类型推断/重载解析/Sendable 那些仍然只有 build 能验 ——
  不许把这个文件的存在读成"编译已经验过了"。
- 变异测试 5 条**全部被抓**,含**精确复现我那个错的形状**(把 import 搬到常量表之后)。
  基线 `7/7✓`(逐字节还原)。
- 现口径:`mutants=52 ran=52 skipped=0 on_new_criteria=36 baseline=7/7✓`。

## 工作树里**不是我做的**两处改动(已核实为正确,我没有提交也没有回退)

工作树是共享的:`AdminUsersPage.ets` 与 `MainPage.ets` 在我提交**之后**被别的进程改过,
两处都是**修构建错误**,都核实过是对的:

1. `MainPage.ets`:把两组 import(`CalendarPage`、`NavItems`)从 `NAV_MATERIAL_OF` 表**之后**
   挪到文件最前 —— 就是上面那条 `arkts-no-misplaced-imports`;
2. `AdminUsersPage.ets`:`Chip(text, bg, fg: string)` → `ResourceColor`
   (`Theme.surfaceMuted`/`textSubtle` 是 `Resource`、`chipNeutralBg` 是 `string`,
   第 368 行那个三目因此是 `Resource | string` ⇒ 旧签名编译不过)。

我不提交别人的活、更不回退它;但它们**让基线必须重算**,而**重算基线是有意动作**
(随手重算会把"某次变异没还原"永久掩盖掉),所以 `baseline.sha` 顶部记了原因与哈希来源。

## 未验

- 这三条判据**只覆盖静态可判的那几类**。`assembleHap` 仍然只有真正构建才能验 ——
  这次就是构建先于我所有判据发现的问题,下次还可能是。
- Go 侧 `debt_registry_test.go` 仍未跑(沙箱无 Go 模块缓存),只有 `gofmt`。
2026-09-15 11:27:35 +08:00