Files
MailUI4Agents/docs/DEV-TOOLING.md
JianFeeeee 8390890646 跨端: feat(对齐): 参照物版本登记(CalendarView.tsx @d78f19f,变了即红)+ 圆角按语义配对(数值来源不同另行登记)
pi 2026-09-14 骨架开工前两件。

1. **对齐参照物要有版本号**:WebUI `CalendarView.tsx` 可能同时在动(gui-lab 有未合入改动),
   照工作副本画完之后参照物一变,这版就成了"照一份没人认领的草案对齐的",而**没人能判它对不对**。
   新增 `docs/ALIGN-REFS.json`(blob 哈希 + 登记于哪个 commit + "以哪次为准")
   + 判据 `test/align-refs.test.mjs`:哈希变了即红,报错按 §14 写明
   「正确修法 = 读差异→判断骨架要不要改→再更新登记」与
   「最常见的错误修法 = 把新哈希抄进去(那是把闸门降级成状态记录)」。变异确认会红。
   当前登记:`d78f19f`「日历页面补上圆角」,工作副本干净 —— 若另有未合入的,合入后再对一次。

2. **圆角必须走令牌,且跨端按语义配对**:鸿蒙侧已有 `Theme.ets:105/107` 的
   `radiusCard`/`radiusControl`(**系统**资源),WebUI 是 `--radius-card: 0.875rem` /
   `--radius-control: 0.5rem`。⇒ 端**语义对齐、数值来源不同**,所以登记写成"按语义配对",
   并且判据要求每条都写明"按语义还是按数值"(否则下一个人会直接去比数字)。
   数值差异本身按形态差异进余额:`radius-card-numeric-divergence`(等设备并排看再决定以谁为准)。
   鸿蒙侧不许把 14 / 0.875 抄成裸数字 —— 与当初 14 处 Material 调色板清零同一形态,量纲换成长度。
2026-09-14 17:46:20 +08:00

6.9 KiB
Raw Blame History

开发工具配置:为什么关掉 pi-lens 的自动改写

本仓库明确关闭 pi-lens 的项目级自动格式化与 autofix。这份文档记录原因, 配置本身在 .pi-lens.json(根目录)。

一句话

pi-lens 编辑任一文件后会「安全格式化」它,而它的默认格式化器与本仓库的手工排版 不兼容 —— 每次编辑都会产生与内容无关的大面积 diff,把真正的改动埋掉。 已经造成过两次真实损失。

⚠️ .pi-lens.json 必须是严格 JSON

pi-lens 的配置加载是:

// pi-lens dist/index.js
PROJECT_CONFIG_BASENAMES = ['.pi-lens.json', 'pi-lens.json'];   // 没有 .jsonc
function parseConfigFile(configPath) {
  const text = fs.readFileSync(configPath, 'utf-8');
  raw = JSON.parse(text);        // ← 不做去注释处理
}
// 解析失败 → 打一行警告,然后**整份忽略**

所以带 // 注释会让这份配置完全失效,而失败方式是静默的: 进程照常跑,只有启动时一行 [pi-lens] ignoring invalid project config。

这个坑真的踩过:第一次写这份配置时把大段理由写成了 // 注释, 于是「已经关掉了」这个结论是假的 —— 防护从一开始就没生效。 现在理由放在本文件里,JSON 里只留一个 $comment 指针。

为什么必须关

pi-lens 在编辑文件后会走 smart-default 回退选择格式化器(见它的 FORMATTER_POLICY_BY_EXTENSION):

扩展名 默认格式化器
.ts .tsx .js biome(默认 tab 缩进 + 双引号)
.html prettier(双引号、<!DOCTYPE html> 变小写、按 80 列折行)

两套默认值都与本仓库的排版冲突。两次已发生的损失:

  1. 19a3161:git add -A 把约 7000 行 biome 重排扫进了功能提交, 那次提交无法审查(还掩盖了一处 Go 文件的删行)。
  2. a404cba:prettier 改写了 client/electron/index.html —— 单引号变双引号、 DOCTYPE 变小写,直接打破 test/theme.test.mjs 的两条断言(该测试要求 同步内联脚本里是 classList.add('dark'),单引号)。

为什么不是「把格式化器配成本仓库风格」

试过:把缩进、引号、lineWidth 全部对齐之后,biome format --write 仍然改动 17 个文件 —— 本仓库的注释按语义换行、数组与调用按可读性手工折行, 这些格式化器还原不了。

谁在守着这个仓库的格式

不是格式化器,是这些:

  • tsc --noEmit(前端类型)
  • go vet / gofmt -l(Go)
  • tree-sitter / ast-grep(pi-lens 的结构规则与安全规则,只读、不改写)
  • 各包的测试套件(npm test、go test ./...、node --test)

相关

  • biome.jsonc:只挡得住 biome,挡不住 prettier —— 两者是并列的候选格式化器, 各有各的配置。所以真正的开关是 .pi-lens.json,它两条改写路径一起关。

部署残留清理(deploy/prune-deploy-artifacts.sh)

部署会留下两类持续增长的东西:网关旧二进制(每份 ~24MB)与插件快照(opencode/dsh 的 快照含 node_modules,一份几十 MB)。2026-09-14 实测 /opt/agentmail 累计到 1.3GB, 其中旧二进制 ~790MB、快照 ~540MB。

bash deploy/prune-deploy-artifacts.sh            # 干跑,只报告
bash deploy/prune-deploy-artifacts.sh --apply    # 真删(默认:网关留 3 份、每插件留 3 份快照)
bash deploy/prune-deploy-artifacts.sh --self-check   # 判据自检(16 项,两侧都验)

三条硬规矩:保留回滚窗口(发布纪律要求有回滚目标,所以不是全清);绝不删正在使用的 快照(扫 /proc 的 cmdline 与 cwd,命中就跳过 —— 删掉它进程一重启就找不到自己的代码); 在线数据库永不入列。

注意那个"在用"判断必须排除本进程及其祖先链:调用方常把路径写在命令行里, 不排除就会出现"永远判为在用"(与 pkill -f 杀掉自己那条命令同一个坑,已写进脚本注释)。

四类残留与各自的窗口

类别 来源 窗口
网关旧二进制 agentmail-gateway.bak-<ts> redeploy-gateway.sh 保留最新 3 份
插件快照 <plug>/<ts> redeploy-plugin.sh 每插件保留最新 3 份,current 永远保留
数据库/附件备份集 backups/agentmail-<ts>.db + attachments-<ts>.tar.gz、data/agentmail.db.bak-<ts> reset-demo.sh 与早期手工留档 保留最新 1 集
/tmp/agentmail-pre-deploy-*.db、/tmp/agentmail-pre-prune-*.db redeploy-gateway.sh、prune-test-sessions.sh 各保留最新 2 份

同一个 <ts> 的库与附件包算一个备份集,一起进出窗口 —— 拆开留没有意义。排序按 文件名里的时间戳而不按 mtime:09-02 的两份备份被 09-08 的一次"打开看一眼"改了 mtime, 按 mtime 排会把最老的判成最新的。没有时间戳的文件一律不碰(判定不了就不删)。 pre-prune 那份是会话归档(不可逆操作)唯一的回滚点,所以它单独一条窗口、报告里也写明身份。

三条判据,以及它们各自防的那个错

  1. 在线库不入删除清单(del() 里的 readlink -f 比对):备份删错能重建,在线库删错回不来。
  2. 每个插件至少留一份"上一版":只有 current 时脚本报 ⚠ 无回滚目标。它只报告、 不造快照 —— 造不出来的东西不该假装有。(2026-09-14 那次事故就是这么暴露的: 四个插件各只剩 current,回滚目标没了。)
  3. --self-check 两侧都验:干净样本该删的删、该留的留、在线库不动必须是绿的; 把窗口外的备份换成指向在线库的符号链接,脚本必须拒跑(退出码 1), 不是"删了才发现"。最后一条是"自检没有碰生产根":比对前后 /opt/agentmail 的清单指纹。

事故记录:自检把生产当成了沙箱(2026-09-14)

--self-check 第一版用 ROOT="$t" … bash "$0" 传假根。脚本读的是 AGENTMAIL_ROOT, 于是这个前缀赋值被静默忽略,自检的 --apply 打在了生产根上,删掉一批回滚备份 (3 个旧网关二进制、8 个插件快照、09-02 的两组备份集)。 为什么没被发现:PRUNE_TMP_DIR 那一路的变量名是对的,所以输出的 /tmp 段看着"确实是假根", 干跑那一轮的报告也像模像样 —— 半对的状态比全错更难认。是 bash -x 里那行 ls -1t /opt/agentmail/… 露的马脚。 改法不是"下次小心":① 传对变量名;② 自检的根目录必须在临时区,否则拒跑; ③ "自检不碰生产"进判据(前后指纹比对)。这条与 pkill -f 杀自己同类: 安全装置自己出错时,产出的是一份看着正常的报告。