Files
MailUI4Agents/client/electron/scripts/release-linux.sh
JianFeeeee 71a3c35610 按 pi 复核改五处:判据的"值/行为"原则、真正的构建门、typecheck 进门、Go 判据零匹配、迁移归属
pi 用反例与变异逐条点了五处,全部**先跑变异再改**(结论都写在原地)。

## 1 判据③:形状正则已删(它永远差一个反例)

实测 pi 的反例 —— `const k = PREFIX + accountId; return PREFIX;`(拼了但没返回)——
对第三版判据**仍然全绿**:第三版锚的是"**函数体里存在**这样的表达式",不是"**返回的**表达式"。
三版的骗法各一个(签名里的参数 / 提了一下没用 / 拼了没返回),都在判"源码里有没有那个形状",
而缺陷是"算出来的值对不对" ⇒ **权威交给行为判据**(`test/stores/background.test.ts` 直接断言
`storageKey('a') !== storageKey('b')`、`=== 'agentmail.background.acct-a'`、不退回全局键),
正则那条删掉并把反例写在原地(否则下一个人会好心加回来)。
保留"键必须来自 storageKey()"那条:那是**来源**约束,不是值对不对,正则在这里合适。
鸿蒙侧只能静态判(`.ets` 本机没有运行时),已把这条限制写进判据说明。
推广进规范:CRITERIA.md §6.7 + run-all 自检关键词(10 → 11)。

## 2 真正的门:`scripts/release-linux.sh`

- 实测 pi 提的变异:**`touch dist/index.html` 时 stamp 判据是绿的** —— 它抓不到"构建失败但碰过 dist"。
  stamp 是**探测器**(抓"src 改了产物没跟上"),门是**喂退出码**,两者不互替(§6.7.1)。
- `build:linux` 里**没有管道**(`&&` 链,退出码本来就传),但那次的哑巴失败是我在命令行手打
  `npm run build 2>&1 | tail -4 && …` 造成的;同时发现它跑的是**裸 `vite build`,跳过 `gen:bg`**。
- 于是把配方收成 `scripts/release-linux.sh`:`set -euo pipefail` + 走 `npm run build` + 再打包。
- 判据是**行为**的:注入失败的构建(`AGENTMAIL_BUILD_CMD='exit 7'`)→ 断言退出码非 0
  **且打包那步没跑**(标记文件不存在)。变异:脚本改成 `|| true` → 红 ✓。

## 3 typecheck 进 `npm test` 链

`npm run typecheck` 原本就有,但没人跑。先修掉它唯一的报错(我自己留下的未使用 import),现在干净;
`test` = run-all + vitest + typecheck。它恰好检查**没被任何测试 import 的文件**(vitest 只解析被测到的图)——
也就是那次 `is not exported by` 的形状。

## 4 Go 源码判据:零匹配 / 读不懂 都要红

改成三分:切不出函数体 → 红;字段在但值不是字面量 → 报「**判据读不懂**」(变异:`BgDim: defaultDim` → 红 ✓);
字段不在 → 红。静默放行是这类判据最危险的失败方式。
**措辞更正**:这条核对的是"与**这份服务端源码**的契约",不是"在跑的服务端二进制是 12/4"
(与"dist 是产物"同构);文档同步改。

## 5 迁移归属:定向做不到,就把"不可恢复"降级成"可恢复"

查实:`accountStore` 的 `activeId` 是**派生视图状态、不落盘**(`persist(accounts)` 只存数组),
所以**本机没有"上次活跃账号"标记可定向** —— 旧值的作者事后无法还原,定向迁移在原理上做不到。
升级前用 B、升级后先登录 A ⇒ A 接管 B 的外观,**一次性错档**,触发条件就这一条。
两件能做的都做了:**写了回读校验**(写不进去就不删旧键,避免净损失;变异:改成先删后写 → 2 条红 ✓)、
**删前另存** `agentmail.background.legacy.bak`(只写不读 ⇒ 不引入新的继承源,判据钉"只写不读")。
§7.12 把本地这半与显形方式写进同一行。

## 验证

`npm test` 退出码 0:14 个判据文件全绿 + vitest **265** 通过(+2 迁移行为测试)+ typecheck 干净;
`hvigorw assembleHap` BUILD SUCCESSFUL;安装包经新脚本重打(dist 与包同批)。
2026-09-14 15:41:52 +08:00

40 lines
1.9 KiB
Bash
Executable File
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.

#!/usr/bin/env bash
#
# 发布 Linux 包:**构建成功才打包**。
#
# 为什么要有这个脚本(而不是在命令行里手打两步):
# `npm run build 2>&1 | tail -4 && electron-builder …` 这种写法里,
# pipeline 的退出码取的是**最后一个命令**`tail`)的 —— 构建失败、`&&` 照走、
# 打包器拿**旧的 dist** 打了个新包,而所有判据都是绿的
# vitest 绿、packaging 绿:它比的是 dist 与包,两边都是旧的,自然一致)。
# 那是真实发生过的一次(见 test/build-stamp.test.mjs 与计划文档 §7.20)。
#
# 两道门,互不替代:
# - `set -euo pipefail` + 顺序调用:**构建失败就不打包**(喂退出码,真正的门);
# - `dist` 比 `src` 新那条判据:**探测器**,抓"src 改了而产物没跟上"。
# 注意它抓不到"构建失败但已经碰过 dist"—— 实测过,那种情况它是绿的。
#
# 构建只有一条路:走 `npm run build`= `gen:bg` + `vite build`)。
# 这里原来写的是裸 `vite build`,那会**跳过 gen:bg**(背景接管用的 CSS 生成步骤),
# 于是生成物缺失/过期时打包器照打不误。
#
# 两个环境变量是给判据用的接缝test/packaging.test.mjs 会注入一个失败的构建,
# 断言它**真的会停下**且不进入打包):
# AGENTMAIL_BUILD_CMD / AGENTMAIL_PACK_CMD
set -euo pipefail
BUILD_CMD="${AGENTMAIL_BUILD_CMD:-npm run build}"
PACK_CMD="${AGENTMAIL_PACK_CMD:-npx electron-builder --linux -c.electronDownload.isVerifyChecksum=false}"
mkdir -p .tmp
export TMPDIR="${TMPDIR:-$PWD/.tmp/${DSH_SESSION_ID:-$(id -un)-$$}}"
mkdir -p "$TMPDIR"
echo "[release] 构建:$BUILD_CMD"
bash -c "$BUILD_CMD"
echo "[release] 打包:$PACK_CMD"
bash -c "$PACK_CMD"
echo "[release] 完成dist 与安装包同批(这一句只在两步都成功后才出现)"