klmtseng/impact-audited

GitHub: klmtseng/impact-audited

一个用 grep 基准交叉验证代码图影响分析结果的轻量审计工具,专治索引器静默丢弃文件导致的依赖关系遗漏。

Stars: 0 | Forks: 0

# 影响审计 **针对代码图“影响分析”的“信任但验证”机制。** 代码智能工具 —— 知识图谱索引器、基于 LSP 的“爆炸半径”分析器,以及为 AI agent 提供代码库映射的 MCP 服务器 —— 专门解答诸如“如果我更改了这个函数,会破坏什么?”之类的问题。它们速度极快,且给出的回答显得十分自信。但它们都有一个隐蔽的失效模式:**如果索引器静默丢弃了某个源文件**(解析器在处理某个大文件时打个嗝就足以导致此问题),所有经过该文件的依赖边都会随之消失 —— 而工具依然会像该文件从未存在过那样给出答案。当某个符号实际上被你代码库的核心代码广泛使用时,你得到的反馈却是*“风险低,只有一个调用方”*。 `impact-audited` 正是为了解决这一问题而生的。它会利用一种极其轻量且无依赖的“基本事实”(即用于查找直接调用点的 `grep`)来交叉验证任何图工具的影响分析输出,并且**两者间的分歧就是关键信号**:如果 grep 找到了某个调用方,而图工具却没有报告它,这就说明索引中缺失了这条依赖边,此时系统会大声向你发出警告,而不是让你盲目信任那种悄无声息的遗漏。 这就是应用于工具领域的*有效性审计*模式:一个**确定性的基础基准**(grep —— 对直接调用方的查找绝对准确)+ 一个**不透明的增强层**(图工具 —— 提供传递性影响、风险评级)+ 一张**独立的确认网**(两者间的差异对比)。 ## 为什么这很重要(实测数据) 我针对两个广泛使用的公共 Python 库运行了一款基于图的影响分析工具(GitNexus 1.6.3)和一个知识图谱 MCP(codebase-memory-mcp 0.8.1),然后将每个顶层符号被报告的调用方与 grep 提取的“基本事实”进行了逐一核对: | 代码库 | 图索引器静默丢弃的核心文件 | 被证明不完整的影响分析结果(严格)/ 受影响范围(宽松上限) | |---|---|---| | [`psf/requests`](https://github.com/psf/requests) | `models.py`, `sessions.py`, `utils.py` | **50%** (28/56 严格标准;64% 宽松标准) | | [`ranaroussi/yfinance`](https://github.com/ranaroussi/yfinance) | `const.py`, `scrapers/history.py`, `scrapers/quote.py`, `utils.py` | **12%** (7/59 严格标准;39% 宽松标准) | 这里的归因极其严密:只有当某个符号的定义刚好位于索引器*保留*的文件中,而 grep 恰好在该索引器自身日志中明确承认解析失败的某个文件内部(排除定义行)找到了真实的调用点时,该符号才会被计入(严格标准)。这意味着该节点存在于图中,但相应的依赖边却绝不可能存在。例如: `requests.utils.to_key_val_list` 被报告为**低风险,仅有一个调用方(`utils.py`)** —— 但实际上,作为该库核心的 `models.py` 和 `sessions.py` 都调用了它。(该符号本身*定义*在被丢弃的文件中,即属于宽松标准范畴 —— 而工具在这种情况下依然给出了答案,并没有大声报错,这正是为什么宽松标准同样值得报告的原因。) 请注意公平性基准:在我的测试运行中,**codebase-memory-mcp 对两个代码库中的每个文件都进行了索引,没有出现任何此类缺口**(复现脚本中并未将这一对比自动化,该脚本主要覆盖 GitNexus 端)。因此,这并不意味着“所有图工具都在撒谎” —— 而是*有些工具可能会静默跳过文件,而你通常无法分辨是哪些工具在这么做*。 这也正是为什么引入轻量级审计极具价值的原因。完整的方法与注意事项请参见:[`benchmark/RESULTS.md`](benchmark/RESULTS.md)。 ## 安装 单文件实现,仅依赖标准库。`tiktoken` 为可选依赖(用于 token 统计)。 ``` curl -O https://raw.githubusercontent.com/klmtseng/impact-audited/main/impact_audited.py chmod +x impact_audited.py pip install tiktoken # optional ``` ## 用法 ``` # 1) 可靠的直接调用者基线 — 无 graph 工具,零 dependencies: ./impact_audited.py to_key_val_list --path /path/to/requests # 2) 审计 graph 工具。--graph 是一个 shell 模板;{sym} = 该 symbol。 # 其 stdout 会被扫描以查找 .py 路径,并与 grep 的结果进行 diff。 ./impact_audited.py to_key_val_list --path /path/to/requests \ --graph 'gitnexus impact {sym} -r requests' # 适用于任何能打印文件路径的工具 — 可以替换 backend: ./impact_audited.py my_func --path . --graph 'other-graph-tool trace {sym} --json' # 3) 机器可读,适用于 CI / agent 工具使用: ./impact_audited.py my_func --path . --graph '...' --json ``` 退出代码 `0` = 审计通过(或未提供图工具);`2` = 图工具遗漏了 grep 找到的直接调用方 —— 其影响分析结果不完整;`3` = 图后端未产生任何输出(缺少工具或命令错误),作为错误而非遗漏进行报告。你可以将其接入 CI 或 agent 循环中,以便在出现静默索引缺口时大声报错。 ## 覆盖与不覆盖的范围 - **覆盖范围:** 符号的直接调用方 —— 这是影响分析查询中风险最高、价值最大的层面。这也正是静默索引缺口造成破坏最严重的地方。 - **不覆盖范围:** 传递性/多跳影响(只有图工具能生成此类结果 —— 但一旦审计标记出缺口,你就会明白其传递性影响的结果也值得怀疑),以及语义/概念查询(对此不存在可用于对比的 grep “基本事实”)。 - `grep 'sym('` 可能会出现多算的情况(如同名方法、字符串、注释中的匹配),因此审计倾向于*标记出潜在问题*。基准测试的核心数据通过仅将结果归咎于索引器自身日志承认丢弃的文件,巧妙地规避了这一问题。 - 测试结果仅针对所测试的工具版本,上游可能已经修复了相关问题;这里的重点在于揭示这种*模式*,而非针对某一个特定工具。 ## 许可证 MIT —— 详见 [LICENSE](LICENSE)。
标签:文档结构分析, 逆向工具