我分析了 Shadcn-UI/UI 中的 200 个 PR 以查找重复项:出乎意料地顺利。

发布: (2026年4月20日 GMT+8 05:41)
9 分钟阅读
原文: Dev.to

Source: Dev.to

PR 冗余审计 – shadcn‑ui/ui

受 Pete 的一条推文启发,内容关于像 OpenClaw 这类高流量仓库的 PR 泛滥。AI 代理在编码方面很强大,但它们也在生成重复的逻辑和与维护者长期愿景不符的 PR。该项目审计 PR 并相应地标记它们。

目标

识别两个(或更多)贡献者在完全不同的方式下解决相同功能问题的情况,通常跨越不相连的文件。

系统并不寻找复制粘贴的代码行;它评估的是架构目标。当发现匹配时,系统会将 PR 分类到以下三类之一:

BucketDescription
SHADOW对同一回归的完全相同的修复。
SUPERSET包含更小、特定修复的更广泛的架构修复。
COMPETING两条不同的路径用于实现相同的功能结果。

下面的所有示例都旨在修复损坏的 /blocks 页面链接。

示例 PR(相同功能失效,不同文件)

PR 编号标题策略修改的文件
#10156fix: update broken link on /blocks page简单 URL 替换apps/www/config/docs.ts
#10088fix(docs): absolute path for blocks link路径规范化apps/www/lib/utils.ts
#10096chore: rename internal block references重构引用键apps/www/registry/registry.json

虽然这些更改涉及完全不同的文件(Config、Utils 与 Registry),系统仍然识别出它们都针对 相同的功能失效 —— 目标重复
PR #10088 解决了根本原因(重命名文件),使得在合并前 #10156 和 #10096 中的文档修复变得多余。

审计结果

  • 200 个最近的 PR 已扫描。
  • 69 条有效冗余 已标记。
  • 以下是一些最有趣的匹配。
PR 标识主要匹配分类为什么重要
#10404 – ThemeHotkey 守卫#10401SHADOWevent.key 的相同空值检查导致 Hotkeys 中的崩溃。
#9895 – 文档复制按钮#9876SHADOW对 bash 命令/文本的相同拆分用于修复复制按钮。
#10421 – DataTable 可访问性#10402SHADOW同时向数据表添加 aria-label
#10403 – Drawer asChild 修复#10139SHADOW为 Drawer 文档添加 asChild 以修复嵌套破损。
#10424 – Monorepo CLI 修复#10258SUPERSET对 monorepo CLI 的更广泛“一次性修复”策略。
#10393 – Geist 字体不匹配#10273SUPERSET比 #10393 更健壮的字体映射。
#10244 – 日历响应式#10235COMPETING对日历宽度响应性的不同 CSS 策略。
#10386 – ThemeHotkey 错误#10404SHADOW对自动填充期间未定义键崩溃的相同逻辑层面修复。
#10383 – FieldSeparator 修复#10201SHADOW两个 PR 都修改同一属性以修复分隔符继承问题。
#10158 – iOS 日期输入#10133COMPETING对同一 iOS 渲染错误的全局 CSS 与组件级修复的竞争。

实现概览

1. 回填脚本(历史审计)

  1. 使用 Octokit 分页获取 PR,目标是关键分支(mainmaster)。
  2. 压缩并过滤 大量 diff,以保持在免费额度范围内:
    • 去除已知的大文件(SVG、lockfile、文档)。
    • 删除注释和未改动的 import。
    • 若仍超过 1500 字符,只保留修改的代码块(+/- 行)。
  3. 使用 Gemini 嵌入模型对每个清理后的 PR 进行 向量化,并存入 Upstash Vector

2. 实时机器人(现场分流)

  1. 当有新 PR 到来时,查询 向量库,获取最相似的 8 条候选记录。
  2. 将这些候选记录传入 LLM 推理循环,判断意图并分配到相应的桶(SHADOW / SUPERSET / COMPETING)。

3. 处理速率限制

  • 路由器会在不同提供商之间自动切换(Gemini、Llama、OpenRouter 等)。
  • 对 503/429 错误采用 3 次重试,并使用指数退避策略。

经验教训

IssueObservationMitigation
Vector Gap同一问题的 PR 采用截然不同的实现方式时,往往在向量搜索中找不到对应项,导致它们从未被 LLM 检索到。添加了一个回退的 “语义‑关键词” 索引(例如提取领域专有词),以扩大召回范围。
Structural Bias早期模型把无关的 JSON 添加误判为重复项,因为它们的结构看起来相似。在构建嵌入时优先考虑 字面值(如 ID、URL),而不是单纯的语法结构。
Model Quota用尽了高阶 AI 配额,只好回退到较小的 8B 模型,导致偏差增大。实现了 预算感知调度器,仅在相似度已经很高时才使用更便宜的提供商。
False Positives仅靠向量相似度会产生大量误匹配。LLM 推理阶段现在会在最终分类前执行 目标对齐检查

要点

  • 历史聚类 冗余 PR 是对任何检测引擎的极佳压力测试。
  • 两阶段流水线(向量相似度 → LLM 推理)在速度和准确性之间取得平衡。
  • 考虑速率限制的设计(免费额度层)对开源工具至关重要。
  • 即使使用了高级工具,人工审查 仍是最终裁决者——尤其是针对边缘案例的 “COMPETING” 修复。

如果您想查看代码或在其他仓库上运行审计,欢迎提交 Issue 或 PR!

Problem

它开始将全新的注册表条目标记为重复,仅仅因为它们在 JSON 结构层面看起来相似。系统实际上忽略了实际的 URL 值,因为它不够智能,无法在内容与结构之间进行权衡。

对宽范围扫描的弱点

在审视大型 PR 时,系统有时会看到并不存在的关系。如果两个大型 PR 恰好都涉及同一个包,系统可能会产生它们之间的关联,即使从逻辑上看,它们毫无关联。

解决方案

backfill engine 现在成为下一步的分析核心:实时 GitHub Bot。通过利用我们构建的历史记忆,Bot 能在新 PR 刚打开的瞬间进行分析,并在已有冗余修复时提醒 maintainers。

未来工作

我也在探索一个 Maintainer Dashboard 来可视化这些语义聚类,为项目维护者提供一个高层次的视图,了解他们的贡献者在哪里意外地重叠。

行动号召

如果你是想在自己的仓库上尝试的维护者,或是想要贡献的开发者,联系我——我很乐意聊聊。

0 浏览
Back to Blog

相关文章

阅读更多 »

Windows 的 Sudo

欢迎来到 Sudo for Windows 的代码仓库 https://aka.ms/sudo 🥪。Sudo for Windows 允许用户直接在未提升权限的终端中运行提升权限的命令 w...