# nexify × graphify 图谱质量对比报告

- **日期**: 2026-09-02
> **注记（2026-09-03）**：验证基建已迁移，本文旧路径 `~/workspace/...` 现为 `~/clawspace/nexify-verify/...`（graphify-codewhale → comparison）。正文路径保留为历史事实。
- **对象**: `~/workspace/codewhale-snapshot`（Rust workspace，21 成员 crate，979 `.rs` + 286 `.ts`，476MB 源码快照）
- **工具版本**: nexify 0.2.1（本仓库 release 构建）× graphify 0.9.53（PyPI `graphifyy`，`uv tool install`）
- **运行环境**: 同一台 VPS（2C），两边都是纯本地 tree-sitter 解析，无 LLM
- **建图命令**: `nexify scan .` × `graphify extract . --code-only`（后者关闭文档语义通道，只比代码图谱）

## 1. 总量对比

| 指标 | nexify 0.2.1 | graphify 0.9.53 |
|---|---:|---:|
| 冷建图耗时 | **38.1s**（extract 20.7 + resolve 17.4） | 51.0s |
| 索引文件 | 1976（git 全量；非源码 files-only 兜底收录） | 1520 code（75 个未分类跳过；`Cargo.toml` 被误判"敏感"跳过） |
| 节点 | **153,640**（13 种 kind） | 52,415（无 kind 分类；含 7,836 个无文件归属的外部占位节点） |
| 边 | 224,557 | 153,295 |
| 边关系 | defines / calls / imports | references(52k) / calls(52k) / contains(33k) / method / imports_from / implements / extends … 共 16 种 |
| 位置精度 | line + col_start + col_end | 仅行号（`L###`） |
| 增量 | blake3 内容 hash，未变不重解析 | manifest 缓存目录，实测同机制 |
| 社区聚类 | 无 | 1,171 个 Leiden 社区 |
| 存储与查询 | SQLite + 13 个 CLI 子命令 + web UI | graph.json + query/path/explain/affected + graph.html/MCP/Neo4j/Obsidian 导出 |

## 2. 核心质量指标：跨文件调用绑定

这是两个工具设计目标的分水岭。同一份代码：

| 口径 | nexify | graphify |
|---|---:|---:|
| 跨文件绑定成功的 calls 边 | **24,860**（另有 306 ambiguous） | **5,122**（4,628 INFERRED + 494 EXTRACTED） |
| 无法绑定但显式保留的 | 103,989 条 UNRESOLVED（带裸标签，可查） | 不产生边（外部符号变成无归属占位节点） |

nexify 跨文件绑定量是 graphify 的 **4.9 倍**，并且区分 AMBIGUOUS/UNRESOLVED 状态；graphify 对绑不上的调用基本静默丢弃。

### 抽查 1：跨 crate 重命名依赖（nexify 胜出）

源码事实：`crates/tui/src/config/home.rs:34` 的 `effective_home_dir()` 调用 `codewhale_paths::user_home()`（`paths` crate 在 Cargo.toml 里改名 `codewhale-paths`）。

- **nexify** `callers user_home`：16 个调用者 = 3 同文件 EXTRACTED + 13 跨文件/跨 crate INFERRED（分布在 app-server / config / state / tui 五个 crate），含上面这条，全部与源码吻合。
- **graphify**：`user_home()` 节点只有同文件 3 个调用者，**全部跨文件调用者缺失**——绑不了 `codewhale_paths::` 这种重命名 crate 限定路径。

### 抽查 2：普通函数跨文件绑定（graphify 也准，但方向不对称）

`effective_home_dir()` 在 graphify 里有 10 条 INFERRED 入边（来自 config.rs / config/paths.rs / lib.rs），抽查 4/4 全部真实（源码行确实调用 `effective_home_dir()`）。但它的**出边**（→ `codewhale_paths::user_home`）缺失。

后果直接体现在查询上：

```
$ graphify path "effective_home_dir" "path_env"
No directed path found.

$ nexify path effective_home_dir path_env
crates/tui/src/config/home.rs::effective_home_dir --calls-->
crates/paths/src/lib.rs::user_home --calls-->
crates/paths/src/lib.rs::path_env
```

### 抽查 3：高频枢纽的召回（差距最大的一档）

`tr()` 是 tui crate 的 i18n 主函数（真实调用量极大）：

| | 调用边 | 分布文件数 |
|---|---:|---:|
| nexify | **877** | 76 |
| graphify | 23 | 5 |

召回差距 **38 倍**。`user_home`（16 vs 3）同属这一档：graphify 的 Rust 跨文件解析只覆盖了少部分普通函数调用。

### 抽查 4：精度抽样（两边都对，nexify 有系统性例外）

各随机抽 20 条 INFERRED 跨文件边回源码逐条验证：

- **graphify：20/20 命中调用点**，加上抽查 2 的 10 条入边，30/30 全对，抽样中未发现一条误绑。
- **nexify：20/20 文本命中**，但其中 2 条（`Err`）是**文本命中、目标错绑**。

nexify 的系统性误绑簇（回源码核实）：

| 误绑簇 | 边数 | 真相 |
|---|---:|---|
| `Err(...)` → `protocol/src/ids.rs::Err`（type alias） | **2,351** | std 构造器，不是那个 `type Err = Infallible` |
| `.write()` → `test_harness.py::write` | 77 | `sys.stderr.write` / `module.write` 等内置方法，还跨到了 vendored `patches/` 目录 |
| `Response.json()` → `github.test.ts::json` | 48 | DOM 方法绑到 test 文件同名函数 |
| `Response.text()` → `*.test.ts::text` | 8 | 同上 |

合计 ≈ 2,484 条，占 INFERRED resolved（24,860）的 **~10%**。根源一致：**裸标签 fallback 唯一命中**时没有 std/builtin/DOM 常用名黑名单。其余 90% 抽样全部正确，包括看起来可疑但实际正确的绑定：`FleetRunId::from`（57 条限定路径绑定全对）、`ViewStack::push`（23 条，方法接收者感知绑定全对）、`ToolContext::new`（617 条真调用）。

### 抽查 5：同名符号聚合

`create_test_app` 在 tui crate 有 25 个同名定义（每文件一个）。两边都能按文件查到各自调用者；nexify 另有查询时实体去重（`defines`/`defined-by` 把 25 个聚合为一个逻辑实体），graphify 没有实体级视图。

## 3. 各自强项

**nexify 明显强的地方**
1. 跨文件调用图深度：绑定量 4.9×，含方法接收者感知、限定路径（`FleetRunId::from`）、workspace crate 路径与重命名依赖（`codewhale_paths::user_home`）——这些 graphify 全部缺失或大面积缺失
2. 绑定状态诚实：AMBIGUOUS / UNRESOLVED 显式落库可查，而不是静默丢边
3. 粒度：字段/属性/变量/模块都是一等节点（88k 变量、15k 字段），`fields/properties/vars` 可直接查
4. 位置到列级；实体去重；SQLite 单一真相源 + web UI；建图更快（38s vs 51s）

**graphify 明显强的地方**
1. **零误绑**（抽样 30/30），绑定策略保守但干净
2. **references 边（52k）**：类型使用关系（`PathBuf`/`Option`/`Config` 的引用网）是 nexify 完全没有的维度，god-nodes 榜单（Config 731、ToolError 583）对架构总览很有用
3. Leiden 社区检测（1,171 个）给出子系统切分
4. 语言覆盖 ~40 种（shell/css/js 都进图），生态工具丰富：graph.html 可视化、MCP server、Neo4j/Obsidian/SVG 导出、跨仓 merge、`affected` 反向影响面
5. 文档/PDF/媒体可入图（配 LLM；本次关闭未测）

## 4. 结论

- **调用图（谁调用谁）**：nexify 质量显著更高——召回 5 倍、绑定手段更高级，代价是 ~10% 的 std 碰撞名误绑（问题集中、可修）。
- **架构总览（类型耦合、社区、枢纽）**：graphify 更好用，references + communities 是 nexify 当前空白。
- 两者的定位其实互补：nexify 是"精确调用图 + 符号数据库"，graphify 是"宽覆盖知识图谱 + 可视化生态"。

**对 nexify 的可执行改进（按优先级）**
1. 裸标签 fallback 加 std/builtin/DOM 常用名黑名单（`Err/Some/Ok/None/None`、`json/text/write/read`…），直接消灭 ~2,484 条误绑
2. fallback 绑定限制在非 vendored/patches 路径，或要求调用方与目标同 crate/同顶层目录
3. 路线图可考虑：`references`（类型使用）边、社区/枢纽榜——SQLite 里都是便宜的查询

## 附：产物位置

- graphify 图谱：`~/workspace/graphify-codewhale/graphify-out/graph.json`（80MB）
- nexify 缓存：`~/workspace/codewhale-snapshot/.nexify/cache.db`（全新重扫，与基线一致）
- 旧缓存备份：`/tmp/nexify-cache-backup.db`（数字与重扫一致，可删）
