Skip to content

测试包只从 main 打包 ​

背景与决策 ​

2026-11-02 同步仓库时发现:内部包 235、236 都是在 Codex 独立 worktree 的功能分支(codex/metric-comparison-round2-20261028)上构建并同址安装的,分支没有合回 main,main 因此落后已安装包 15 个提交。根因有三条:

  1. 每个 AI 任务在独立 worktree/分支开发,交付后没有合并回 main;
  2. AGENTS.md 只要求推送“当前分支”,没有要求从 main 打包;
  3. 包内 Info.plist 不记录源码提交,从 App 本身无法判断来源。

当天已把该分支无冲突合入 main(5f8f3c15),并核对 236 构建前固定的 176 个源文件 SHA 与 main 全部一致,因此已安装的 236 即为 main 产品代码,不重打 237。

Project Owner 2026-11-02 当次明确要求同时落地两项:规则与构建保护。本批由 Owner 直接指示执行,没有另立 Lead 方案文档;记录在此以满足 C6。

实际修改 ​

文件修改
AGENTS.md工作流程新增“测试包只从 main 打包”:签名/交付/标准安装包必须来自已推送到全部远程的 main 提交;分支工作先合并再打包;交付汇报写明提交号;放行开关仅限本地实验。
MacApp/scripts/build-app.sh在 swift build 之前新增源码来源检查,并在 Info.plist 写入 PerfowlSourceCommit、PerfowlSourceBranch、PerfowlSourceClean、PerfowlSourceGate,构建结束打印 SOURCE_COMMIT/SOURCE_GATE。

门禁规则 ​

  • 只在设置了签名身份(PERFOWL_CODESIGN_IDENTITY 非空且不是 -)时强制;ad-hoc 本地开发构建照常可打,PerfowlSourceGate=not-checked。
  • 必须同时满足:当前分支是 main;git status --porcelain -- MacApp 为空(含未跟踪文件,因为 MacApp/ 下未被忽略的文件都可能被打进包);HEAD 与每个已配置远程的 refs/remotes/<remote>/main 相同。
  • 远程比较使用本地跟踪引用,不在构建时联网;推送会同步更新跟踪引用,因此“已推送”判断成立。跟踪引用过期时宁可拒绝,提示先 fetch/推送。
  • 不满足时退出码 1 并列出全部原因;PERFOWL_ALLOW_NON_MAIN_BUILD=1 显式放行时继续构建,但包内标记 bypassed,按 AGENTS.md 不得安装为标准测试客户端或描述为交付。
  • 非 git 目录记为 unknown,签名构建一律拒绝。

相对口头建议的偏差 ​

  • 口头建议中写的是“工作区不干净即拒绝”;实现收窄为只检查 MacApp/。原因:站点、文档、验收工具的未提交改动不进入 App 包,若全仓检查会让并行的文档工作阻断打包。
  • 变量与中文全角标点相邻时须写成 ${VAR}:在 UTF-8 locale 下 bash 会把全角逗号当成变量名的一部分,首轮测试中出现过 unbound variable,已修正。

验证(E2) ​

  • bash -n MacApp/scripts/build-app.sh 通过。
  • 用临时 bare 仓库(两个远程)对抽出的门禁段落做 9 个正反例,系统 /bin/bash 3.2.57,LC_ALL=en_US.UTF-8 与 LC_ALL=C 各一遍,结果一致:
场景期望结果
干净 main、两远程已推送、签名通过 passedexit 0
只推送到一个远程、签名拒绝exit 1,指出未一致的远程
同上但不签名构建继续 not-checkedexit 0
MacApp/ 有未跟踪文件、签名拒绝exit 1
仅 MacApp/ 之外有改动、签名通过exit 0
功能分支、签名拒绝exit 1
功能分支、签名、显式放行继续 bypassedexit 0
功能分支、身份为 -继续 not-checkedexit 0
非 git 目录、签名拒绝exit 1
  • 真实脚本在本仓库(MacApp/ 有未提交改动)以签名身份运行:0.6 秒内、swift build 之前拒绝。门禁只执行少量本地 git 命令,相对 236 记录的约 380 秒完整构建可忽略,不引入联网、轮询或全盘扫描。

站点构建(partial) ​

  • npm run build(Node v24.19.0,本机为此通过 nvm 安装,未改默认 Node):知识门禁 PASS(66 个 Registry 契约),归档同步 862 个文件,Mermaid 浏览器资源重新生成 209 个文件;随后分阶段构建在服务端打包阶段达到构建器固定的 180 秒总时限而终止,未进入死链检查阶段。同一 Intel 主机 2026-10-28 已记录过同类超时,与本批改动无关;构建器时限未改。
  • 替代核对:新增 devlog 页与归档快照文件均存在,时间线节点只引用这两个目标;git diff --check 通过。
  • 旧机器 2026-10-08 生成的 site/public/vendor/mermaid/(旧格式、被 gitignore、可由 node_modules 重建)被同步脚本按设计拒绝覆盖;已移到会话临时目录,未删除。
  • 本批不涉及指标验收,未发布网站。

遗留 ​

  • 尚未用新脚本完成一次完整签名构建来实证 Info.plist 新键(E2→E3);下一次产品代码变更后的内部包(237)会自然覆盖,届时核对 PerfowlSourceCommit 与 main HEAD 一致。
  • App 界面尚不显示源码提交;如需在“关于”中展示,另立方案。
  • 本机两个 Codex worktree 仍在旧分支上;后续任务应从最新 main 新建分支,完成后合回 main 再打包。

Validation Update · 2026-11-02:内部包 237 从 main 构建并同址安装(E3) ​

  • 来源:main 7a5748e7,用新脚本以 Developer ID 签名完整构建,未设放行开关。包内 PerfowlSourceCommit 等于 main HEAD,PerfowlSourceBranch=main、PerfowlSourceClean=true、PerfowlSourceGate=passed。门禁在真实签名构建上实证通过,上文“遗留”第一条关闭。
  • 构建:596.1 秒(主工作目录无既有缓存,核心采集组件从头冻结;236 在有缓存的工作目录中为约 380 秒,两者条件不同,不作性能对比)。pymobiledevice3 11.3.1 与旧版采集器沿用 236 的做法,从已安装包复用;核心采集组件由当前源码重新冻结。构建前固定 456 个 MacApp/ 源文件 SHA,打包前复核未变。
  • 校验:App 与 DMG 严格签名;DMG hdiutil verify 通过;冻结核心 107 个源码模块与 CLI 均与 main 源码一致;挂载 DMG 后文件树与构建产物一致;安装后文件树与 DMG 一致;安装后核心 probe 返回 ready。
  • 产物:MacApp/dist/Perfowl-237-macos-x86_64-internal.dmg,148,236,852 B,SHA-256 70700170b889e93ac05f14c4298738a6e72bf69339287ecf518faae8c8acda45;dist 仅此一包及校验文件。
  • 安装:先确认客户端与采集进程均未运行、无进行中的 Session,再把 236 打包成回滚压缩包并解包核对文件树一致,随后原子替换 /Applications/Perfowl.app,失败时自动还原(本次未触发)。回滚包与收据保存在仓库外的私有目录。
  • 未完成:公证按 Owner 内部测试边界继续暂缓,Gatekeeper 评估 exit 3、stapler exit 65;未做手机侧 E4 冒烟;未跑 Swift/Python 全量回归,因为 237 的产品源码与已完成回归的 236 一致,仅构建脚本有变化。

Implementation Update · 2026-11-02:启动器只保留一个 Perfowl(E3) ​

  • 问题:Owner 反馈启动台出现两个 Perfowl。LaunchServices 登记中有 4 个 Perfowl 路径:/Applications/Perfowl.app;237 打包时的 DMG 源目录(私有目录 pack-root/Perfowl.app,264 MB,被 Spotlight 索引,即启动台第二个图标);以及两条已不存在路径的残留登记(旧机器的 build74 本地归档、237 回滚核对目录)。
  • 处理:注销并删除 pack-root(DMG 已校验,且 DMG 挂载后与安装后的文件树都与它一致,可从 DMG 重建);注销两条残留登记;killall Dock 刷新启动台。复核后 lsregister -dump 与 mdfind -name Perfowl.app 都只剩 /Applications/Perfowl.app。没有改动已安装的 237 和正在运行的客户端。
  • 规则:AGENTS.md「测试包与数据清理」新增“启动器唯一”:每次打包覆盖本机后,删除暂存 App 或放进 .noindex 目录,用上述两条命令核对只剩一个,残留登记用 lsregister -u 注销;核对结果写入交付汇报,多于一个不得交付测试。
  • 脚本:私有安装脚本已在安装后自动删除暂存目录、注销多余登记,并断言只剩 /Applications/Perfowl.app,结果写入安装收据。脚本在仓库外,下一次打包安装时实证(E2)。

Perfowl · Performance Observer