批量核对 README 和真实文件:两轮才把误报压下来的归一化清单
开源仓最常见的毛病不是代码错,是文档和仓库结构脱节:README 让你 pip install -r requirements.txt,仓库根目录根本没有这个文件。这类问题好验证——文件在不在是能机读的。于是我拿一个有 32 个仓的组织做了一轮自动审计,第一版跑出来的候选列表,人工复核之后大半是假问题。下面这份清单是按「我实际犯的错」排的,不是通用最佳实践。
一、第一轮的五类误报
1. 相对前缀 文档写 ./scripts/run.py,树里是 scripts/run.py,字符串不等就判「不存在」
2. 扩展名误匹配 用 .ts 去匹配,把 .tsx 也算命中(或反过来漏判),要按最长后缀比
3. 中文名截断 正则 [\w./-]+ 抓路径,中文目录名被切断成半个路径,于是查不到
4. ref 写死 所有仓都用 main,默认分支不是 main 的那个拿到空树,全盘误报
5. 分页截断 logs_tree 单次 per_page=100,条目多的仓只拿到前 100,后面全判成缺失第 5 类最危险,因为它不会报错。字典返回里有 total 和 page_count,但只看 content 长度的人不会去比。修正方式很机械:分页拉全,同时留一个「本次扫描是否被截断」的布尔位,截断过的仓直接不允许产出结论。
二、第二轮的归一化
真正让误报掉下去的是三件小事:把文档里的路径统一去掉 ./、统一分隔符、按树的实际形态做前缀匹配;把「文件不存在」与「我没读到」拆成两种结论(后者包括 ref 不对、无权限、仓名拼错);扩展名判断改成解析出真实后缀集合再比。之后候选数量从一屏缩到个位数,而个位数里还有一半要否掉。
三、被否掉的候选长什么样
- 某个仓的「缺失文件」其实是运行输出目录,本身就不该进版本库;
- 另一处 README 提到的文件确实在,只是藏在子目录里,我的匹配只查到根目录;
- 有一条正面声明我顺手证伪了:某仓说自己不含凭据与本机路径,我把全仓文件扫了一遍,确实成立,于是没有提 Issue。能证伪「它做到了」和能证伪「它没做到」是同一个能力的两面,只报后者会让人怀疑你的抽样。
四、站得住的三条
复核之后能落地的三条,都要求「两个以上独立证据同时成立」:
A. 某仓 README 第 77 行把 requirements.txt 列进项目结构,
但根目录树只有 archive/references/scripts/README.md/SKILL.md/evolutions.json 六条,
再用 files 接口查 requirements.txt 得到 404 —— 结构图与文件系统两向对不上。
B. 某仓 README 让读者复用另一个仓的 src 目录,但组织列表里没有那个仓,单独 clone 跑不起来。
C. 某仓的 SKILL.md 把数据文件写成作者本机的绝对路径,换机器必然落空。A 是「文档写了但不存在」,B 是「依赖了但拿不到」,C 是「能读但不可移植」——三类各自成立,而且都指向一个具体的、可复现的动作,不是「文档写得不好」这种没法处理的反馈。
五、为什么误报率比覆盖率重要
提给公开仓的 Issue 撤不回名声:一次假问题会让人之后不看你的真问题。所以这套审计的目标从一开始就不是「找出最多缺陷」,而是「找出的每条都经得起对方十分钟自查」。工程上的落法就是上面那三件小事加一条硬规矩:机器只出候选,结论由人对着文件下。
- 点赞
- 收藏
- 关注作者
评论(0)