Vendorwake 用代码证据核验依赖升级风险
Vendorwake 读取供应商更新日志,将发现标为已确认、潜在或不受影响;已确认结论需要符号引用与 API 变更证据,或升级后的失败测试支持。模型可以解释或降低风险等级,但不能自行将发现升级为已确认。
AI 深度解读
依赖升级最费时间的,往往是判断更新日志里哪些变动会碰到自己的代码。Vendorwake 把这件事串成了一条流水线:读取官方变更、定位仓库引用、切换版本跑测试,再生成补丁并复测。
作者用 stripe-python 15.6.1 → 16.0.0 跑了一次完整调查,约 13 分钟交出结果。其中一个补丁修错了,系统也明确标了失败。这个案例值得看的地方,是它怎样限制 AI 下结论,以及哪些结果仍然不能放心相信。
什么证据才配叫「确认受影响」
Vendorwake 给调查结果分了三个等级:
- Confirmed:有确定性证据,例如代码准确引用了已删除或改名的 API,或者测试在新版本下失败。
- Potential:模型认为存在关联,但还缺少证明。
- Unaffected:没有使用对应供应商或受影响符号。
关键规则是:模型可以解释结果,也可以降低等级,但不能把结果升级为 Confirmed。这条限制写在代码里。
「确认受影响」的权限,不能交给负责猜测关联的模型。
证据从官方资料开始建立。SerpApi 搜索只负责找到候选页面,搜索结果本身不算证明。系统随后从供应商官方域名抓取正文,优先使用 HTTP;页面只有 JavaScript 外壳时,再交给 Browserbase 渲染,并保留 session ID。
抓到的内容会计算哈希,存入 TimescaleDB hypertable。没变化的页面可以跳过,每条发现也能追溯到当时读取的具体内容。
Gemma 4 把发布说明提取成结构化变更,包括类型、严重程度、受影响符号、替代方案和原文引句。随后,程序检查引句是否真的出现在来源中。供应商文本按不可信数据处理,测试里植入的「ignore previous instructions」被标记,没有被执行。
这一步确实抓到了模型的问题。演示中,两次 SerpApi 搜索找到官方 changelog,Gemma 从 16.0.0 中提取了 41 项变更,但有 4 条引句、10 个符号被发现经过改写。因此结果保留了 needs human review 标记。
仓库侧则靠 manifest 解析器和 Python AST 扫描器查找依赖、导入、属性链与关键字调用,再由规则匹配符号和版本范围。模型负责解释关联,并组织「供应商来源 → 变更 → 符号 → 文件 → 测试」的证据图。图上的连线也要有依据,不能只因为模型觉得两件事有关。
测试证明升级会坏,也证明补丁可能修错
演示使用一个小型计费 fixture,依赖固定为 stripe==15.6.1。目标版本是原文称于 2026-09-30 发布的 stripe-python 16.0.0。
仓库分析在 requirements.txt 中识别到版本,检测置信度为 95%,并定位了这些引用:
- payouts.py 使用 stripe.Reversal。
- invoices.py 使用 invoice.request(...)。
- customers.py 使用 customers.retrieve(customer=...)。
- catalog.py 使用 Stripe,但没有使用受影响 API。
系统在全新的 virtualenv 中运行测试:15.6.1 下通过,16.0.0 下失败。三个受影响文件被确认,catalog.py 被判为 Unaffected。invoices.py 的发现包含 5 项确定性证据和 1 项模型推断。
例如,invoice.request(...) 在升级后报 AttributeError,提示 request 不存在,并给出「Did you mean: '_request'?」。这比「新版本可能存在兼容问题」更接近开发者能直接处理的任务:文件、行号、调用和失败结果都已经摆出来了。
接下来,Gemma 为每个受影响文件生成一份 unified diff。stripe.Reversal → stripe.TransferReversal 的修改正确,但 invoice.request(...) 被替换成了 raw_request(...)。后者返回原始 StripeResponse,原代码继续访问 sent.id,于是再次失败。
所有补丁应用到 16.0.0 后,测试结果是 3 passed、1 failed。页面把建议标成「Verified: failed」。批准补丁也只是记录决定,不会自动应用或推送。
能证明旧代码坏了,不代表已经证明新补丁修好了。
系统的文字解释也没有完全可靠。作者承认,模型生成的摘要写到了测试从未产生的 KeyError。因此,证据判定和叙述文字需要分别看待。
另一个表现较好的例子是追问「不打补丁,哪个文件先坏」。Backboard 检索调查记忆后,Gemma 回答现有上下文无法确定顺序,界面也展示了它使用的那一条记忆。它没有拿文件列表冒充执行顺序。
免费跑通了,但还不是可靠的常驻服务
项目以 Apache-2.0 开源,技术栈是 FastAPI、Temporal、PostgreSQL/TimescaleDB/pgvector 和 Next.js。各供应商通过适配器接入,业务逻辑不直接导入供应商 SDK。
模型使用 gemma-4-31b-it,回退到 gemma-4-26b-a4b-it,经 Google AI Studio 免费层和 OpenAI-compatible adapter 调用。作者称,切到 vLLM 或 Ollama 只需调整配置。原先使用的 OpenRouter 免费 Gemma 池受到上游限流,才换到这里。适配器还会在校验输出前移除 <thought> 块,因为该环境的 Gemma 4 总会先思考,并拒绝 thinking budget。
这次调查约耗时 13 分钟,模型费用为 $0。Sentry trace 有 315 个 spans:版本对比 2.8 分钟,影响评估 1.3 分钟,补丁提议 7.4 分钟。后者受免费层每分钟 16K tokens 的节奏限制。
Temporal 负责分析、发现、调查和验证工作流,步骤返回前先保存输出;遇到 429 时按 Google 要求的延迟重试。但托管演示将 Temporal 嵌在免费 Render 服务中,服务休眠或重新部署会丢失工作流历史。报告和时间线仍在 Postgres,中途调查却可能一直停在「running」。Render 闲置后的首次请求还需要约一分钟唤醒。
资源也有限制。512 MB 实例曾因加载 ONNX embedding model 而 OOM,因此使用 bge-small embeddings、由 pgvector 支撑的「相关历史变更」只在本地运行,线上关闭。
权限设计比自动执行更克制。discovery、repository、impact、verification、migration 各有 Auth0 machine identity,工具调用检查真实 token。migration 的 propose_patch 获准,push_branch 因缺少 repo:write 被拒绝。GitHub 目前使用只读 token,没有接入 Auth0 Token Vault;免费计划也不提供异步审批 CIBA,所以审批放在应用内。
验证仅面向允许列表中的仓库,免费托管沙箱还无法彻底切断网络。这些都是把演示搬进团队环境前必须处理的实际缺口。
我的判断
我认同它把提取、判定和执行拆开的做法。相比只让 AI 阅读 changelog 并给升级建议,Vendorwake 多交出了代码位置、版本对比和补丁复测结果,开发者更容易检查它究竟凭什么下结论。
但效果证据还很窄:这是一个小型 Python fixture、一次 Stripe 升级调查。原文没有提供大型仓库、多语言项目或大量供应商上的准确率,也没有与人工处理、普通依赖升级机器人做耗时和成本对照。约 13 分钟是这次运行的记录,不能当作普遍收益。
它是否比现有升级流程更有用,还取决于测试质量。测试没有覆盖到的行为,版本切换后仍可能出问题;测试通过,也只能说明当前用例没有发现失败。前端或 Node 团队可以借鉴流程,但原文实际展示的是 Python AST 扫描,不能直接认定它已具备同等的 JavaScript、TypeScript 分析能力。
开源、开放权重和来源快照有助于审查。作者进一步提出可重跑并获得相同证据,这是设计目标;原文没有给出多次运行的一致性数据。尤其是模型摘要已经出现虚构异常,页面上的自然语言仍需要对照测试记录阅读。
能拿来做什么
- 给日常 AI 升级建议加上证据等级。涉及删除 API、参数改名或返回类型变化时,要求列出官方原句、代码位置和验证结果;缺少证明的关联保留为 Potential。
- 在前端或 Node 项目中借鉴「旧版本、新版本、补丁后」三轮验证流程,优先选择已有测试覆盖的依赖升级任务。迁移前先补关键行为测试,才能判断 AI 是否保住了原有语义。
- 让 AI 编程助手先生成可审查的 diff,再执行独立验证。审批记录、补丁应用和分支推送应当分别控制,避免一次批准顺带放开后续写入权限。
- 保存每次调查的来源快照、模型版本、测试日志和工作流标识。排查失败时先看这些记录,再读模型摘要,尤其要核对异常类型、返回对象和失败顺序。