From f43d63da78011f93a8655672f932ca63543dcfcb Mon Sep 17 00:00:00 2001 From: Mavis Date: Mon, 2 Nov 2026 09:54:07 +0800 Subject: [PATCH] docs(agents): record that the packaged asar is not bit-reproducible The 0.78.1 detail wave was rebased onto the merged manage wave and rebuilt. The rebuilt asar has a different sha256 from the build the independent verifier checked, even though the two trees differ only in the port document and a build-script comment. The cause is that the packaged asar is not bit-reproducible. node-gyp writes the absolute build path and a random temp directory into the tree-sitter native objects, and the renderer bundle copies embed the random upstream extraction directory. So equality has to be shown file by file. --- AGENTS.md | 1 + 1 file changed, 1 insertion(+) diff --git a/AGENTS.md b/AGENTS.md index b0b918ae..e286693c 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -137,6 +137,7 @@ npm run frontend:build # 构建可读 renderer 重建 | **实机对比官方 UI 时,目录是异步加载的,早量会读少章节**(2026-10-31 实证) | 两侧目录都是运行时拉取,首帧为空 ⇒ 在目录到达之前量章节,读到「为你推荐 + 10 chips」= 11,和官方的 13 差两节 ⇒ **像移植漏了章节,其实只是量早了**;同一坑也让 chip 行少一个可见 chip(可见 chip 是「前五个有数据的 chip」,少一条就顺移一位) | 探针打开弹窗后**轮询到目录到达再量**(至少等 2.5 s 并重测一次),两次读数都记录。两侧的章节标题、chip 行、native 标记、市场已发布条目要**一次性同口径比对**,别把加载时序差当数据差 | | **详情页的 pane 跳过条件只能按 kind 写死 skill,不能写 `Me!=null`**(2026-11-01 实测,官方 0.78.1 → 0.18 连接应用详情页) | 一个旧补丁把 pane 级 scroll pane 的跳过条件写成 `Me!=null?Rs:…`(0.62.0 的 skill 详情自带 scroll 区),官方 0.78.1 的 `ki()` 只对 skill/bot 走直出、plugin/installed/setup 全包 pane ⇒ 插件详情丢了 32px 内边距,宽 898 而不是官方的 834,看着像「CSS 没搬全」,实际是结构少包一层 | 条件收窄到 `Me!=null&&E!=null&&E.kind==="skill"`,并加守卫断言 bypass 含 `E.kind==="skill"` 且不含裸 `Me!=null`(`tests/skill-detail-renderer-patch.test.mjs` 的 only-the-skill-detail 那条)。判据永远是**宽度**:详情 834 = 898 − 64,两边都得是 | | **官方的 logo tile 和上游的 ToolIcon 不是同一个配方,1px 和边框都藏在这里**(2026-11-01 实测) | 官方 `AD` 的 logo 分支是 border-box + 0.5px 半透明边框 + 透明底 + `object-fit:contain` 的图;上游 0.18 的 ToolIcon 是 content-box + 次级底色 + cover 的图 ⇒ logo 大 1px(55→56)、细边框缺失,DOM 类名看着都对 | logo 分支按官方字节重写(`RM0781LogoIcon`,半径取 `Math.round(edge*0.28)` 即 40→11、56→16),mono 回退和 native 分支不动;守卫断言 tile 类串和 `sand-19kjcj4`(contain)逐字节等于官方 | +| **打包产物的 `app.asar` 不可逐字节复现,比 sha256 证明不了「两个构建是同一产物」**(2026-11-02 实测) | 同一棵树在两个 worktree 里打包,`app.asar` 的 sha256 **也**不同 ⇒ 想证明「verifier 验证过的构建 == 新 head 的构建」时,比 sha256 必然不相等,很容易误判成「改动没生效」或「产物被污染」。根因是打包产物里有两个独立的 per-build 字节来源:① `node-gyp` 生成的 `dist/node-deps/tree-sitter*/build/Makefile` 里写死了**绝对构建路径**和**随机临时目录**(`.tmp-tree-sitter-node-XXXXXX`),编译出的 `binding.o` / `parser.o` 同样含路径;② renderer bundle 副本里嵌了**随机上游解包目录名** `grok-upstream-module-XXXXXX`。这两类还会连带改动 `dist/reconstruction-build.json` 与 `dist/renderer-0721-visualization.json` 两个哈希清单 | 必须**逐文件比对**:解 asar 头(JSON 在 offset 16、长度 `readUInt32LE(12)`、数据起点 `8 + readUInt32LE(4)`,节点的 `offset` 是**字符串**必须 `BigInt`),列出两边的文件清单与每文件 sha256;实测两次构建 1337 个文件、无增无减,**只有 5 个不同**,逐个证明差异落在上述两类里即可,补丁写入的文件必须**逐字节相同**(本次是 `view-B5Ug8wEm.js` 与 `index-lCyB53CO.css`)。⚠️「同一路径内构建产物 sha256 == 部署后 sha256」那条**不受影响**,它仍然成立 |