|
|
d47035aaff
|
docs(dev-tooling): 补三条 —— 布局改动的回滚账、PIPESTATUS 与 pipefail 是判据的一部分、判据输出要自证比完全部对象
第 10 条是 pi 提的:把 lib/user-question.js 搬到 test/lib/ 的收益是'快照更干净',
但**回滚它会让快照立刻多出一处运行时漂移** —— 这类改动的账里没有'回滚'这一行。
第 11 条把管道纪律写清取法,并点明四个 deploy 脚本的 set -o pipefail 不是风格而是判据。
第 12 条来自实测:show_diff 的 cmp|head 在 set -e 下让脚本当场中止,
只报第一个对象、退出码却恰好还是 1 —— 判定对、证据被截断。
|
2026-09-14 20:35:10 +08:00 |
|
|
|
44fdfb3ed7
|
fix(deploy-drift): 判据 ① 的覆盖面写进 note(0 必须带上可证伪范围)+ 记录 C 的取舍 + docs 补 4 条纪律
pi 的 C 项(`.bak` 那次修法"把圈往外挪了一格,还是圈")我**实测后决定不改**,理由留档:
- 这一格现在**零违规**:`/etc/systemd/system` 133 个文件里**没有任何一个**含仓库路径,
包括现存的 4 个 `.bak`(`dsh-lan.service.bak-20260903-081410`、
`pi-bridge.service.bak-13010-20260814`、`pi-bridge.service.bak-20260814`、
`pi-web-sessiond.service.bak-20260814`)—— 全干净;
- pi 提到的 `zcode.service.bak-20260912-145744` **他读时已经 ENOENT**(他自己写了),
也就是说我引他那句话时依据的文件**已经不存在**;
- 扩到"每个普通文件都读"在当前只会引入噪声(二进制/dpkg 数据库类),换不到真信号。
⇒ 改为**把覆盖面写进 note**("比了 129 个 … 文件")——
`0` 只有在"它能被证伪的范围"写明之后才是结论,这正是这条判据当初缺的那句话。
等真出现一个非白名单后缀的违规再改,那时我们就有实例了。
docs/DEV-TOOLING.md 补 4 条纪律(编号 7-10,原第 7 条顺延):
7 「注入点会把该抓的 bug 藏起来」(含位置选择器 `bad[0]` 的同类);
8 「看起来在比、其实没比」要当一条自查(本轮出现三次:路径错/空目录/符号链接),
且**绿的时候也要留下覆盖范围的证据**;
9 **变异之前先提交**(我未提交就变异 + `git checkout` 还原,把自己的改动冲掉);
10 **注释里的数字无法被判据守住**(同文件三处说法三个数、式子加起来还是错的)。
自检全过;实跑 ① 报"比了 129 个文件"。
|
2026-09-14 20:25:24 +08:00 |
|
|
|
a1ed4ea1a5
|
docs(dev-tooling): 变异纪律补两条 —— 判据退出码不许经管道取值(tail 改写了量纲)+ 新判据上线先找相反的不变量
第 6 条是我自己刚踩的:`bash check-shared-libs.sh 2>&1 | tail -25; echo $?` 拿到的是
tail 的退出码,于是那条脚本的红(真值 1)被我报成 0 —— 只因为失败信息走 stderr 没进管道
才露出来。第 7 条是这轮最贵的一课:新的'不可达就搬走'与既有的'共用模块逐字节同源'
方向相反,我只看⻅了自己那条,差点让下次部署静默删掉 dsh 桥的生产模块。
|
2026-09-14 20:14:47 +08:00 |
|
|
|
d616582e96
|
fix: 回滚 user-question.js 那一搬(它把 check-shared-libs 打红两处),并把 drift 的非运行时差异摘出来
pi 逐处对文件后指出:我按"本平台不可达 ⇒ 搬去 test/lib/"把 `lib/user-question.js`
搬走,打红了 `deploy/check-shared-libs.sh` 两处(实测确认,脚本真退出码 1):
共用模块缺失:plugins/pi-mail-bridge/lib/user-question.js
共用测试已分叉:test/user-question.test.mjs(opencode vs pi)
根因不是取舍而是口径:**`lib/` 上挂着两条方向相反的不变量** ——
① 共用模块四方逐字节同源(`check-shared-libs.sh`,连相对路径一起钉);
② 本平台生产可达(我新加的规则)。而 `user-question.js` **是 dsh 桥的生产代码**
(`plugins/dsh-mail-bridge/src/index.ts` 引用它)⇒ 两条必然冲突。
**`lib/` 首先是四桥共用命名空间,其次才是"本平台可达"**;可达性只能当**报告**,
不能当搬家判据。教训的形状:**一条新判据上线时,先找它可能与哪些既有不变量冲突** ——
我只看⻅了自己那条。
改动:
- `user-question.js` 与它的测试回到 `lib/`、`test/`(路径也与 dsh 侧一致),
两边逐字节相同已复验;`check-shared-libs.sh` 退出码 0。
- `reach.mjs` 增加 `sharedLibNames()`:直接从 `check-shared-libs.sh` 的 `ALL_LIBS`
读共用清单做豁免(不手抄常量),并把"进快照但本平台不可达"降级为**报告**。
- `layout-boundaries.test.mjs` 增加回归判据:共用模块必须留在 `lib/`、
测试相对路径与 dsh 一致、两侧逐字节相同。
- 删掉 `reach.mjs` / `docs/DEV-TOOLING.md` 里那句**无据的机制说明**
("user-question 走前缀动态 import"):`localRefs` 的三条正则只认引号字面量,
对模板字面量形状是**盲的** ⇒ 那句若为真,搬走的就是生产代码而两条判据都会绿。
pi 读了 `src/` 下九个文件都找不到引用,我也确认是记忆偏差;理由改用 `addressing.js`
(传递可达、`src` 直接引用数为 0)—— 它已足够证明"直接引用数不是可达性"。
顺带按 pi 的第二条建议:`deploy/check-deploy-drift.mjs` 判据 ① 把
**非运行时差异**摘出来(`jsonTestOnlyChange`,只豁免 `scripts.test` 一类字段,
只对"两边都在、仅内容不同"的文件生效)。理由:一条**永远黄、没人打算为它动手**的判据
唯一的下场是被学会忽略,那时真正的运行时漂移会被一起忽略。
⚠️ 摘的条件很窄 —— **把运行时差异误判成非运行时比恒黄更坏(那是假绿)**,
所以 `main`/`start`/`dependencies` 变了、或解析不了,一律仍算运行时;
纯函数加了六个反/正样本的判据(含三个"必须算运行时"的)。
(该文件同时有另一条会话的改动,未提交、我未触碰;本次只加了我这一段。)
验证:`npm test` 463/463;`check-shared-libs.sh` 退出码 0;`--self-check` 18 条全过。
|
2026-09-14 20:11:58 +08:00 |
|
|
|
6b1cca0fe4
|
docs(dev-tooling): 加一条提交纪律 —— 多 agent 共用工作区,提交前先看 git status 里有没有别人的文件
这个工作区是多条会话共用的:2026-09-14 20:02~20:04 另一条会话正在改
deploy/install.sh、deploy/prune-deploy-artifacts.sh、deploy/redeploy-gateway.sh
(-trimpath 那组加固),而我同时在同一个仓库里连续提交。
`git add -A` 会把别人没写完、没审过的改动一起做进我的提交,且从 git log 看不出归属。
规矩:显式列出要提交的路径;提交信息里不把别人的改动算成自己的。
(本次三次 pi-bridge 提交都是显式路径,事后用 git show --stat 核对过没有混入。)
|
2026-09-14 20:05:15 +08:00 |
|
|
|
e49f0a8f6a
|
docs(dev-tooling): 写点三处**不同的入口假设**、过宽过窄、因果无关判据、锚点、lib/ 边界 + 一条被自己纠正的观察
按 pi 的两条建议补:
1. "漏过三次"改成**列出三次的位置与各自不同的入口假设**(他指出的问题:原写法
会让读者以为"同一处错了三次"):① `writeSession` 只包 `writeFileSync`;
② `mk()` 的 `mkdtempSync` 在 try 之外;③ 兜底层放在 `main()` 而 `selfCheck()` 是导出的。
三次都概括成一句:**"我以为的入口/哪一行"决定了覆盖范围**。
2. "判据只能发现已知成因"作为实例加进同节,并配对写出**因果无关**的运行期判据
(`test/lib/run-suite.mjs` 数结果行 / 跨文件重名实测不被拦)。
新补四条(本轮新踩出来的):
- **判据过宽和过窄都是坏的**(那条 import 判据自己同时踩过两边);
- **判据的锚点必须与结论一一对应**(重名检查锚结果行 vs 锚"名字出现过",
噪声与效应恰好同阶 ⇒ 4 看起来还能解释);
- **`lib/` 与 `test/lib/` 的边界**(部署脚本是 `cp -a` + `rm -rf test`,
没有 `EXCLUDE_DIRS` 这种变量;★ 别写成"被 src/ 直接 import"—— 直接引用数不是可达性);
- **附一节"被自己的结论半路纠正的观察"**:那条 `result IS NULL` 的挂起请求看着像
授权链缺口,实际是网关按设计处理的(`PermissionWaitWindow = 10min` + 推导出的
"失效时刻")。教训写成"先查完'是否已由另一层按设计处理掉'再下结论"——
这类误判会以"我发现了新问题"的语气传播,比沉默更贵。
|
2026-09-14 20:00:52 +08:00 |
|
|
|
d735e674e1
|
docs(dev-tooling): 判据纪律那节 —— 三种"看起来验过了"的失效形态 + 变异纪律 + 两条实现纪律
pi 复核后提出的收尾:跨文件的教训现在没有容器(实证散在三个文件的头注释里)。
先 `ls docs/` 看过:`docs/DEV-TOOLING.md` 已经有"三条判据,以及它们各自防的那个错"
那一节,主题完全相同 —— 所以**并进去而不是新开一篇**(这是 pi 明确要求的形状)。
写的是**可迁移**的那部分,实证不复述、只给索引:
- 三种失效形态:**钉装饰**(断言落在注释上)、**分支退化**(绑在会变的环境上)、
**跑不到的分支**(断言在、区分力不在 —— 短路是无声的,比退化更狠);
- 变异纪律 5 条:先证明能还原再注入、只对已干净提交的文件做、还原路径不得依赖被测资源、
判据不得用被测物证明自己、别只看过滤后的输出(也**不要**为此引入手抄的期望数常量);
- 两条实现纪律:测试文件之间不许互相 import(会二次注册整套用例,实测 475→459);
写点覆盖范围不得取决于入口(这条在这套代码里被漏过三次);
以及"判据过宽和过窄都是坏的"—— 那条"测试文件互相引用"判据自己同时踩过两边。
- 索引指出:`check-deploy-drift.mjs` 的运行输出**就是**部署状态的判据来源,
**不要**抄成哈希清单往外发(发给 jianf 的那份在两次提交后就作废了)。
|
2026-09-14 19:52:41 +08:00 |
|
|
|
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 |
|
|
|
69b1887eae
|
chore(deploy): 清理部署残留(1.0GB)+ 把清理写成可复跑脚本
用户说「清理一下」。实测 /opt/agentmail 累计 1.3GB:
- 网关旧二进制 33 份 × 24MB ≈ 790MB(每次 redeploy 留一份,从 09-05 起没清过)
- 插件快照:opencode 6 份 339MB、dsh 7 份 195MB、zcode 16 份、pi 9 份
- /tmp 里的部署前数据库备份 10 份(tmpfs,占内存)
新增 `deploy/prune-deploy-artifacts.sh`(可复跑,不手敲 rm),两条硬规矩:
① **保留回滚窗口**:网关留最新 3 份、每个插件留最新 3 份快照,`current` 永远保留
(发布纪律要求有回滚目标,所以不是全清);
② ★ **绝不删正在使用的快照**:扫 /proc 的 cmdline 与 cwd,命中就跳过。
执行结果:**/opt/agentmail 1305MB → 302MB(释放 1003MB)**,7 个服务全部 active,
`current` 指向未变,`check-deploy-drift` 仍报「四个宿主都在跑当前代码」。
## 过程中的一处自纠
"在用"闸门第一版有**自我匹配**缺陷:我的测试命令把路径写在命令行里,于是扫 /proc 时
扫到了自己 ⇒ 对不存在的路径也判"在用"(与 `pkill -f` 杀掉自己那条命令同一类)。
已改为排除本进程及其祖先链,并**换正确方式重测**(路径从文件读、不进 cmdline):
在用快照判"在用" ✓、不存在的路径不误判 ✓ —— 判据两侧都验过才敢执行删除。
文档:docs/DEV-TOOLING.md 记了用法与那两条规矩。
|
2026-09-14 08:43:54 +08:00 |
|
|
|
33e44074e7
|
fix(tooling): pi-lens 的项目防护其实一直没生效(JSON 里带注释 → 整份被忽略)
## 现场
跑 `pi --help` 时有一行不起眼的警告:
[pi-lens] ignoring invalid project config …/.pi-lens.json:
Expected double-quoted property name in JSON at position 60
`.pi-lens.json` 是 `d50c55d` 专门加的项目级防护(关掉 pi-lens 的格式化与
autofix),但它的说明写成了 `//` 注释 —— 读 pi-lens 的源码确认:
PROJECT_CONFIG_BASENAMES = ['.pi-lens.json', 'pi-lens.json']; // 没有 .jsonc
raw = JSON.parse(text); // 不去注释
// 解析失败 → 打一行警告,然后**整份忽略**
所以「已经关掉了」这个结论是**错的**,防护从落地那天起就没生效过。
而它要防的是两次已发生的真实损失:一次是 `19a3161` 把约 7000 行 biome 重排
扫进功能提交(无法审查、还掩盖了一处删行),一次是 prettier 改坏
`client/electron/index.html` 并打破 `test/theme.test.mjs` 的两条断言。
失败方式是静默的:进程照常跑,只有启动时一行警告 —— 而我正是在
`pi --help` 的输出里才看见它。
## 修
- `.pi-lens.json` 改为**严格 JSON**(只有 `$schema` / `format` / `autofix`;
`$comment` 也不行 —— pi-lens 校验未知键,会为它刷一条
「unknown key … ignored」的警告,而噪声会训练人忽略告警)。
- 理由移到 `docs/DEV-TOOLING.md`(含 pi-lens 的源码依据、两次事故、
以及「为什么不是把格式化器配成本仓库风格」——试过,仍改 17 个文件)。
- `biome.jsonc`(允许注释)里加指针:它只是两道闸中的一道,真正的总开关是
`.pi-lens.json`,而那份**必须是严格 JSON**。
- 验证:`pi --help` 现在 **0 行** pi-lens 输出;反向对照(故意塞回一行注释)
会重新出现 `ignoring invalid project config`。
## 顺带:仓库里有一个活的凭据
`scripts/verify-l2.sh` 把**管理员 user key 硬编码**在文件里(`1759666` 起就在
git 历史里)。实测它**仍然有效**(`/auth/me` → 200),属于用户 `jianf`。
- 已改为从 `VERIFY_L2_TOKEN` 或 `/root/gotmp/verify-l2-token.txt`(600)读取,
两者都没有时**报错退出**(反向对照验过:EXIT=2,不静默跑);
- 跑通一次确认可用(6 通过 0 失败)。
**但删掉当前这行不能把它从历史里拿掉** —— 要真正作废必须轮换那把 key。
这需要你定(它是你账号的密钥,可能还有别的工具在用),见提交后的说明。
|
2026-09-12 23:49:55 +08:00 |
|