bmmmm/comparereleaseii

GitHub: bmmmm/comparereleaseii

该工具通过对比代码 diff 对发布说明进行事实核查,逐条验证文档声明是否与实际代码变更一致,并发现未被文档覆盖的静默变更。

Stars: 0 | Forks: 0

# 比较 release ii 根据实际的代码 diff 对发布说明进行事实核查。 ## 快速开始 适用于任何 GitHub 仓库或本地的 git clone —— 选定一个仓库,选定一个版本,即可得出裁定结果: ``` $ git clone https://github.com/bmmmm/comparereleaseii && cd comparereleaseii $ pnpm install $ node src/cli.ts restic/restic --tag v0.19.1 --html report.html ``` 要求 Node ≥ 24 以及已通过身份验证的 [`gh`](https://cli.github.com)。借助 [`claude`](https://code.claude.com) CLI(或 `ANTHROPIC_API_KEY`),您可以获得由 LLM 裁定的结果;如果两者都没有,该工具会优雅地降级,仅执行确定性阶段的检查。`--estimate` 可在首次运行前预览所需工作量。 完全本地的裁定可通过任何兼容 OpenAI 的服务器(Ollama、MLX、LM Studio、vLLM)实现 —— 不会向外部发送任何数据: ``` $ node src/cli.ts owner/repo --engine openai --model qwen3:8b $ OPENAI_BASE_URL=http://127.0.0.1:8080/v1 node src/cli.ts owner/repo --engine openai --model my-model ``` 诚实的校准说明:本地的 Qwen3.5-9B 在黄金数据集上(`pnpm eval`)的得分为 6/8 —— 这对于批量验证已经足够,但在重构仅仅看起来像修复时,它可能会过度验证微妙的安全声明。对于关键版本的发布决策,建议使用更强大的评估模型,或者在使用本地模型对安全声明得出 `verified` 结论时需谨慎对待。解析器可以容忍小型模型生成的 JSON 缺陷(例如会自动修复未闭合的对象)。 发布说明即声明。此工具用于验证它们:它会提取一个版本,将说明拆分为原子声明,并根据该版本与其前身之间的实际 diff 检查每一项声明 —— 此外还会进行反向检查:找出哪些代码变更*未*被任何说明所涵盖(静默变更)。 ## 工作原理 每项声明都会经历一个逐级递进的检查流程 —— 首先进行低成本的确定性检查,仅对仍不明确的内容调用 LLM 进行裁定: 1. **锚点** —— 将声明中引用的 PR 编号、commit SHA 与发布范围内的提交记录进行比对解析。 2. **词法** —— 将从声明中提取出的代码标识符(`code spans`、`SCREAMING_CASE`、camelCase、文件名、深层版本号)通过 grep 在 diff 的变更行中进行检索。 3. **排序** —— 根据 diff 中的 hunk 与声明的相关性进行排序(微型 tf-idf + 路径加权),以筛选出值得进行评估的证据。 4. **LLM 裁定** —— 将声明和排在前面的 hunk 发送给模型(默认:通过 `claude` CLI 使用 Haiku),由其作出 `verified`(已验证)/ `partial`(部分验证)/ `no_evidence`(无证据)/ `contradicted`(相矛盾)的裁定,并引用具体的代码行作为证据。评估模型最多可以一次性请求查看三个特定的已更改文件(受控的二次检索轮次),而对于可能导致发布失败的裁定(`no_evidence`、`contradicted`),系统将通过 3 次投票取中位数的方式进行确认。所有裁定结果都会存入本地磁盘缓存中 —— 如果数据未发生更改,重复运行是免费的,且生成的结果在比特级别上完全一致。 反向(完整性)检查会标记出那些变更未被任何声明所涵盖的提交。以下两项改进确保了该检查的可靠性: - **自动生成条目检测** —— 如果自动生成的 "Title by @user in #N" 列表条目的标题与 squash 提交的标题完全一致,由于其在构造上必然为真,因此在评分中仅赋予 1/4 的权重;而手写的声明才是发布说明中容易撒谎的地方。 - **冗余审计** —— 对于模糊的声明(如 "Updates and fixes"),会转换检查思路:要求评估模型列出该说明*隐藏*了哪些值得关注的变更(如新增的 endpoint、行为变更、添加的 dependency),并对它们进行标记。 涉及的函数会从 unified-diff 的 hunk 头部信息中提取出来,并作为证据标签显示(例如:`fns: register_access, should_block_host`)。 在针对每一项声明的裁定之外,每次运行还会根据以下三个组成部分计算出一个可解释的**信任分数**(0–100): - **正确性** —— diff 能够支持的变更声明的比例 - **完整性** —— 发布说明所涵盖的代码变更量(按行数加权)的比例 - **风险** —— 100 减去由风险标志产生的扣分项:敏感路径(auth/crypto、CI/build、dependency 清单)中未记录的变更、静默添加的 dependency、二进制/压缩/不可读的 blob 文件、install-hook 的变更 如果存在相矛盾的声明或关键风险标志,总分将会被强制限制上限 —— 虚假的发布说明无法通过平均分把成绩重新粉饰为合格。此外,系统还会显示仓库上下文信息(代码规模、语言构成、发布节奏),以便进行校准。 使用 `--baseline `(默认值为 5,数据源为 GitHub)时,系统会将之前的多个版本作为异常检测的基线:例如异常的版本体积、首次在敏感路径上提交代码的作者,以及首次出现的二进制文件,都会基于该仓库自身的历史记录被标记出来。使用 `--history ` 会打印发布时间线,而不是执行检查: ``` $ node src/cli.ts dani-garcia/vaultwarden --history 6 tag date commits files ±churn claims anchored sensitive deps+ bin 1.37.0 2026-07-24 27 90 10385 45 100% ci,dependencies,auth 4 0 1.36.0 2026-05-03 18 54 1304 38 100% ci,dependencies,auth 0 0 … ``` ## 环境要求 - Node.js ≥ 24(原生运行 TypeScript,无需构建步骤) - [`gh`](https://cli.github.com/)(已通过身份验证),用于获取 GitHub 源数据 - [`claude`](https://code.claude.com/) CLI,作为默认的评估引擎;或者配置了 `ANTHROPIC_API_KEY` 并使用 `--engine api`;亦或使用 `--judge off` 仅执行确定性检查 ## 使用方法 ``` $ node src/cli.ts juanfont/headscale # latest release $ node src/cli.ts --local ~/src/myrepo --base v1.2.0 --head v1.3.0 # local clone $ node src/cli.ts owner/repo --tag v2.0 --notes-file draft-notes.md # check a draft ``` 选项说明: ``` --tag Release tag to check (default: latest release) --base Base tag/ref to diff against (default: previous release) --local Use a local git repo instead of the GitHub API --notes-file Check this notes file instead of the published notes --judge auto | all | off (auto: LLM only for unclear claims) --engine claude-cli | api | off --model Judge model (default: haiku) --md / --json Write markdown / JSON reports --html Write a self-contained visual HTML report --fail-on none | contradicted | no-evidence (default: no-evidence) --estimate Print a cost/effort estimate instead of judging --no-cache Bypass the on-disk verdict cache ``` `--estimate` 用于在首次正式运行前回答“这会消耗多少成本?”:它会提供声明分类明细、计划调用的 LLM 次数、输入 token 数量、实际耗时以及 API 成本预估。 一个典型的版本(约 45 个声明,90 个文件)需要调用 10 到 15 次 Haiku,通过 API 的花费约为 $0.07,而通过 claude CLI 约需 2 到 3 分钟;在缓存已存在的情况下重新运行只需几秒钟。 退出码说明:`0` 表示所有声明均有据可查 · `1` 表示发现了无依据或相矛盾的声明(可用于 CI 拦截) · `2` 表示指令用法或数据错误。如果您希望设置一个相对宽松的 CI 拦截门槛,可以使用 `--fail-on contradicted`,这样即使存在无法验证的声明(例如尚未公开的安全公告)也能予以容忍。 `--html` 报告是一个不包含任何外部资源依赖的单体文件:内含信任分数环、裁定结果条形图、风险标志,以及一个展示 diff 的树状图(Treemap)—— 其中方块面积 = 变更的代码行数,颜色 = 文档记录状态,琥珀色边框 = 敏感路径。如果在 auth 相关路径中存在未记录的变更,它在图中会显示为一个带有琥珀色边框的巨大红色方块。 ## 基于真实版本的验证 该检查工具不依赖于特定的发布说明书写格式 —— 已通过验证的场景包括:GitHub 自动生成的 PR 列表、手写的安全说明部分、Keep-a-Changelog 文件、使用 Setext 格式及 Issue 锚点的说明(如 restic),以及包含完整 SHA 列表的变更日志(如 headscale): | 版本 | 说明风格 | 得分 | |---|---|---| | headscale v0.29.2 | 散文式叙述 + 完整的 sha 列表 | 96 (详实) | | git-cliff v2.13.0 | Keep a Changelog, conventional commits | 91 (详实) | | restic v0.19.1 | setext 章节, issue 锚点, cherry-picks | 90 (详实) | | vaultwarden 1.37.0 | 自动生成的 PR 列表 + 手写安全声明 | 79 (存在轻微遗漏) | | vaultwarden 1.37.0, 伪造的说明 | — | 5 (可疑), 退出码 1 | 在检查 vaultwarden 1.37.0(包含 45 个声明,27 个提交,90 个文件)时,系统针对安全声明找到了具体的证据,即使相关的安全公告目前仍处于未公开状态: ``` ✔ Send Access-Count Bypass GHSA-rxhg-2pw9-vf25 verified (0.95) — atomic access-count check-and-increment in a single SQL UPDATE in register_access(); the comment states concurrent accesses could both pass the check and exceed the limit. ``` 同时,它会如实地指出哪些内容是公开的 diff 所无法证明的,而虚构的声明则会被直接识破: ``` ✘ The icon endpoint was removed entirely in this release contradicted (0.90) — routes() still registers icon_internal and icon_external; the diff shows refactoring, the endpoints remain active. ``` ## 开发说明 ``` $ pnpm install $ pnpm check # tsc --noEmit $ pnpm test # node:test unit tests $ pnpm eval # judge eval against the golden set (needs an engine) ``` 没有任何运行时依赖;`gh`、`git` 和 `claude` 均作为子进程被调用。 ## 支持 如果您觉得这个工具对您有帮助,可以在 [ko-fi.com/bmabma](https://ko-fi.com/bmabma) 支持我们的开发。 ## 许可证 GPL-3.0-or-later — 详见 [LICENSE](LICENSE)。
标签:Git工具, MITM代理, 开源框架, 持续集成, 网络安全研究, 自动化攻击