跨端: 修打包坑(构建失败被管道吞掉)+ dist 新鲜度判据;判据从"窗口式"改成同表达式

接手 pi 的 WebUI 开项途中踩到三个坑,都已修好并配判据(承接 e94313f)。

## 坑 1:`npm run build 2>&1 | tail -4 && electron-builder …` 吞掉构建失败

pipeline 的退出码是 `tail` 的 → 构建失败、`&&` 照样往下走、electron-builder
**拿旧的 dist 打了新包**。而所有判据都是绿的:
- vitest 绿(见坑 2);packaging 绿(它比 dist vs 安装包,两边都是旧的,自然一致)。

新增判据:**dist 必须比 src 新**(build-stamp)。变异:`touch` 一个 src 文件 → 红;
重新 `npm run build` → 绿。错误信息写明"注意别把它的退出码丢在管道里"。
已重构建 + 重打包(deb 与 app.asar 同批,15:19)。

## 坑 2:测试通过 ≠ 能打包

真正的失败:`AGGREGATE_ID` / `isUsableAccount` 被我当成 `accountStore` 的导出
(它们住在 `lib/accounts.ts`)。vitest 263 条全绿,生产构建直接报
`"AGGREGATE_ID" is not exported by "src/stores/accountStore.ts"` ——
测试运行时对缺的具名导出是宽容的(拿到 undefined)。**生产构建是一道独立的门。**

## 坑 3:判据写成"窗口式",被自己的变异测试抓住两次

`appearance-defaults` 的"取键函数必须把账号拼进去":
1. 第一版从 `export function` 切到 `}` → **参数表里的 accountId 满足了正则**,
   把实现退回全局键仍然全绿(假判据!);
2. 第二版只取函数体 → `return accountId ? PREFIX : PREFIX;`(提了一下没用)又骗过去;
3. 第三版要求**同一个表达式里既有常量又有账号的插值/拼接**:
   两种退化都红,合法的 `PREFIX + accountId` 写法仍然绿。

三种变异都验过(红/红/绿),还原后基线绿。

## 文档

§7.12 两行改为「已修」并写明依据(默认值=服务端契约;缓存键差异已消除,旧全局键
只作一次性迁移源);新增 §7.20 记这三个坑与推论(产物是 gitignore 的,
"源码修好"≠"用户手上那个包修好")。

## 验证

`npm test` 退出码 0(13 个判据文件全绿 + vitest 263 passed);
`hvigorw assembleHap` BUILD SUCCESSFUL;`npm run build` + electron-builder 均 exit 0。
This commit is contained in:
2026-09-14 15:20:30 +08:00
parent e94313f66a
commit dbdb2f5039
4 changed files with 114 additions and 8 deletions

View File

@ -516,9 +516,9 @@ deb 也不必从 targets 里摘。已写进 `client/electron/BUILD.md`(含排
| 动效 | 自定义 transition/时长 | `animateTo` + 系统 `curves` | 动效曲线应跟随系统设置"减弱动效" |
| 遮罩 | 自声明 `--bg-scrim` + `--bg-dim` 两段式 | 系统 `sys.color.ohos_id_color_mask_regular` | 遮罩要随主题换向浅色洗白/深色压黑这件事系统已经做了 |
| **品牌色** | `--c-blue-600: 37 99 235` | `Theme.accent = '#2563EB'` | **不允许差异** —— 两个客户端是同一个产品 |
| **本地外观缓存的键** | 全局常量 `agentmail.background` | **按账号**`appearance.<accountId>` | **鸿蒙是对的,不许为"对齐"退回全局键** —— 全局键的后果是切到服务端没有记录的账号时`saved=false` 分支会把**上一个账号的外观** push 上去新账号"继承"了外观而且写进了服务端)。pi 2026-09-14 确认这条记在 WebUI 侧为开项换键或至少在把继承来的值当"本地的"推给从未有记录的账号前停一下 |
| **本地外观缓存的键** | `agentmail.background.<accountId>`**已修**原来全局 | `appearance.<accountId>` | **差异已消除**2026-09-14 dsh 接手 pi 的开项两端都按账号分键且都留有不许退回全局键的判据全局键的后果是切到服务端没有记录的账号时 `saved=false` 会把**上一个账号的外观** push 上去新账号"继承"了外观写进了服务端)。WebUI 侧保留旧全局键**仅作一次性迁移源**接管后立刻删除且未登录时不迁移 |
| **遮盖色的令牌** | `--bg-scrim`浅色白 / 深色黑"朝底色淡化" | `Theme.wallpaperScrim` = `sys.color.ohos_id_color_background`同向`Theme.overlay` = mask **只用于模态弹层** | **不允许混用** —— mask 两套主题下都是深色浅色 `#99182431`拿它当壁纸遮盖会在浅色主题下压暗 WebUI 反向)。两个语义两个令牌理由与实测值见 §7.17b-2 |
| **遮罩浓度的默认值** | 两套store `dim=24/blur=8` `lib/appearance.ts` `clamp(...,12,4)` | 12 / 4只有一套 | 服务端**缺字段**时真正落地的是 `clamp` 的默认值所以按 12/4 对齐WebUI 那两套值迟早要统一pi 记在他那边 |
| **遮罩浓度的默认值** | `12 / 4`**已修**原来 store `24/8` `clamp` `12/4` 两套并存 | 12 / 4只有一套 | **不是审美,是服务端契约**pi 更正了自己上一封`DefaultAppearance()` 明写 `BgDim: 12, BgBlur: 4` 且注释宣称"与客户端默认值一致" —— WebUI 24/8 使那句注释为****。现已统一到共享常量 `src/lib/appearanceDefaults.ts`判据**直接去 Go 源码读**这两个数比对本来后果很重服务端"没有记录"时客户端以本地为准推上去**新账号的初始外观由第一个同步它的客户端决定** |
**关于 `overlayColor` / `overlayAlpha` 消失**pi 要求把删除理由记在这里否则下一个人会当成漏改补回来
鸿蒙这边的模态走**系统弹窗**`bindSheet` / 自绘 `Stack` 只做位置遮罩本身用系统遮罩色
@ -773,6 +773,38 @@ pi 指出"邻接不是结构"这条已经在同一个仓库露头**三次**
判据要点用户真正会点的那一层。另外补了一条本仓刚踩的:**验证要按真实入口跑**
`node --test test/run-all.mjs` 会把 runner 内部的 `process.exit(1)` 吞掉)。
### 7.20 接手 pi 的两个 WebUI 开项dsh2026-09-14两个实缺陷 + 途中踩到的三个坑
pi 明确说他那条链上**没有 shell**,而挂着的两个开项虽然读得出精确修法却没人执行;
他担心的是它们"以 §7.12 已记录的样子漂着,看起来像已处置"。**结论:我接**,两件都做完(`e94313f`
各配判据 —— 见 §7.12 那两行的「已修」。
**坑 1最值得记`npm run build 2>&1 | tail -4 && electron-builder …` 会把构建失败吞掉。**
pipeline 的退出码是 `tail` 的 —— 于是构建失败、`&&` 照样往下走、electron-builder
拿**旧的 dist** 打了一个**新的包**。而所有判据都是绿的:
- vitest 绿:测试运行时对"缺的具名导出"是宽容的(拿到 `undefined`),只有打包器会报;
- packaging 绿:它比的是"dist vs 安装包",两边都是旧的,自然一致。
已加判据:**dist 必须比 src 新**`build-stamp` 里;变异:`touch` 一个 src 文件 → 红),
错误信息里写明"注意别把它的退出码丢在管道里"。
**坑 2测试通过 ≠ 能打包。** 真正的失败是 `AGGREGATE_ID` / `isUsableAccount`
被我当成 `accountStore` 的导出(它们住在 `lib/accounts.ts`。vitest 263 条全绿,
**生产构建直接报** `is not exported by`。**生产构建是一道独立的门**,前端改动必须过它。
**坑 3我把判据写成了"窗口式"的,被自己的变异测试抓住两次。**
`appearance-defaults` 里"取键函数必须把账号拼进去"那条:第一版从 `export function` 切到 `}`
—— 参数表里的 `accountId` 就满足了正则,于是"把实现退回全局键"**仍然全绿**
第二版只取函数体,但 `return accountId ? PREFIX : PREFIX;`(提了一下、没用)又骗过去了;
第三版要求**同一个表达式里既有常量又有账号的插值/拼接**,才既抓住两种退化、
又不误伤合法的 `PREFIX + accountId` 写法。
**规范第 1 条(判结构要配对/解析、不靠邻接与窗口)的适用对象包括"我自己刚写的判据"。**
**一条推论**`dist` / 安装包是**产物**`.gitignore` 忽略),所以"源码修好了"不等于
"用户手上那个包修好了"——改前端要 `npm run build` **再** `electron-builder`
并用刚加的那条判据确认产物不旧。本次已重构建并重打包deb 与 app.asar 同批)。
### 7.19 两条跨端约定pi 2026-09-14 复核后确认)
- **`Theme.` 的成员名不改**pi 三条理由:判据钉的是"值来自系统 + 品牌色仍手写"