关于 Sinter
Sinter 是面向编码 Agent 的本地代码知识图谱命令行工具,以有证据支撑的符号关系分析代码库,并增量更新图谱。它提供结构导航、影响分析和任务证据包,避免将未确认的关系当作事实。
主要功能
- 01增量构建类型化代码图谱
- 02跨文件及跨语言影响分析
- 03符号路径与变更影响查询
- 04按图遍历范围进行文本搜索
- 05生成任务编辑与测试证据包
适用场景
- 01接手陌生代码库时查看模块结构
- 02评估符号变更影响及相关测试
- 03查找概念对应的代码位置
- 04跨仓库分析服务依赖影响
MCP 相关
Sinter 可在初始化仓库时注册 MCP 集成,并通过 MCP 向客户端提供代码图谱查询。CLI JSON 与 MCP structuredContent.data 使用相同的数据结构。
配置
本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。
工具
本地服务需要在你的电脑上运行后才能读取工具,维护者暂未提供工具列表。
详细介绍
sinter
专为编码 Agent 打造的本地代码知识图谱,以单个静态二进制文件交付。
sinter 使用 tree-sitter 构建仓库符号的带类型有向图,并以增量方式保持图谱最新。在陌生仓库中运行 sinter map,即可获取有界的结构清单,其中包含模块节点/文件计数、按图入度衡量的依赖枢纽、文档入口点和图谱健康状况的局限。它不会推断运行时入口点或领域归属。接着,可利用图谱开展有针对性的工作:
- 反向影响范围 — 哪些内容传递依赖某个符号,跨文件、跨语言(
sinter affected)。遍历会在枢纽处停止并标出枢纽;除非特别要求,否则只统计依赖该符号的测试,不列出具体测试。 - 路径 — 一个符号如何到达另一个符号(
sinter path)。 - 差异影响 — 变更集可能影响哪些符号和测试(
sinter impact),以及用于检查重构是否未完成的--expect <symbol>:查找差异未触及的某个符号的直接依赖项。 - 有界文本搜索 — 以图遍历结果为搜索范围的正则表达式搜索(
sinter grep '<regex>' --within 'affected(<sym>)'),取代先运行受影响项分析、再对文件进行 grep 的流程。 - 多语言、零配置 — 纯语法图无需 LSP 即可使用。当语法提供必要的类型信息时,sinter 可以解析 self 接收者、本地类型化接收者、类型化字段,以及显式的静态/类调用。要完整绑定接收者调用,通常需要最新的 SCIP 索引;零配置不等于完整的编译器级解析。
- 经过校准的词法导航 —
sinter ask根据名称、文档、路径、签名、字符串字面量和有限的调用证据,对包含实质内容的起始点进行排序。置信度行反映排名最高结果的证据类别;--explain会补充排名差距区间,以及该区间的留出集计数和 95% 置信区间(留出集只有 46 个案例,因此区间较宽)。该区间不是每个结果的概率;ask是导航工具,而非语义问答引擎。 - 符号概览 —
sinter show会将选定符号转换为精简卡片,其中包含其定义(也包括属性)和一行“被使用情况”统计;--body会添加源代码(能在 60 行内显示时展示全文,否则最多显示至字节预算),--impls会添加该类型的 impl 块,而show @file:line会标出所在的外层符号。超过 8 KB 或 200 行的代码跨度是无法通过正文转储展示的黑洞:卡片会改为概述其内容,列出其中的嵌套定义、字面量分支和命令字面量,并标注行号(--outline可强制启用)。 - 任务证据包 —
sinter context "<task>"会将任务中的标识符解析为实际节点名称(必要时使用模糊匹配,并以term ~> symbol的形式显示),再以这些名称为种子,返回编辑候选项、提及任务词语的字符串字面量和人工维护的镜像,以及可运行的命令形式的受影响测试,并注明每项测试由哪个符号触达。只要有匹配项,它就不会弃答。添加--workspace <manifest>,即可在一个证据包中对已声明的成员仓库中的候选项进行排序。 - 限定快照的断言 —
sinter assert no-callers <symbol>会在明确的语料范围内检查深度为 1 的调用边。其判定结果为violated、holds_for_indexed_snapshot或not_proven之一;它绝不会声称已穷尽运行时情况。sinter assert deletable <symbol>会统计所有范围内深度为 1 的依赖项,并按范围分组。 - 引文维护 —
sinter cite <symbol>会生成带有稳定符号键的 Markdown 位置引用。sinter verify-doc <file.md>会重新解析受管理的引文;遇到已移动、缺失、无效或不含身份信息的引用时会失败。 - 跨仓库工作区 — 面向分布式系统的多仓库联邦图:支持跨服务边界分析影响范围、路径和 PR 影响(使用
--workspace)。 贯穿一切的设计规则:要么有证据,要么什么都没有。 只有结构、作用域、导入或编译器(SCIP)证据将引用绑定到定义时,边才会存在(工作区清单可以添加由操作人员声明的跨仓库链接,而 Rust trait 实现会添加带有dynamic标签的动态分派扇出,使影响范围在dyn Trait下仍然可追踪)。 歧义一律归为空——“未解析”是一个一等且计数的结果,绝不靠猜测。每条边都会携带其证据类型,每个查询都可以据此筛选。要清楚了解不使用编译器能做到什么:仅基于语法的证据只能绑定通过作用域和导入可以证明的名称,其余情况(接收者调用、重新导出、宏)都保持未解析,因此零设置图是精确的子集,而非完整图。在有编译器索引可用的情况下,sinter scip可以弥补这一差距。
安装
包管理器:
cargo install sinter-io # or: cargo binstall sinter-io (prebuilt)
uv tool install sinter-io # or: pipx install sinter-io
brew install shellfu/tap/sinter
它们都会将名为 sinter 的二进制文件放到 PATH 中。也可以使用单行命令,无需依赖项(Linux 和 macOS;会验证发布校验和,并安装到 ~/.local/bin):
curl -fsSL https://raw.githubusercontent.com/shellfu/sinter/main/scripts/install.sh | sh
Windows,在 PowerShell 中运行(较新且尚未经过充分实战检验;会验证发布校验和,并安装到 %LOCALAPPDATA%\sinter\bin):
irm https://raw.githubusercontent.com/shellfu/sinter/main/scripts/install.ps1 | iex
要根据 GitHub 构建来源证明验证手动下载的发布资源(需要 gh CLI):
gh attestation verify sinter-<target>.tar.gz --owner shellfu
PyPI wheel 通过 Trusted Publishing 携带 sigstore 来源证明。安装后,sinter update 会从 GitHub releases 自动更新自身。
也可以从源代码构建(需要 Rust 工具链):
cargo build --release
快速开始
只需要可用本地图的 Agent,无需安装钩子或编辑客户端配置,即可创建派生状态:
sinter ensure /path/to/repo
此命令只会构建或刷新 .sinter/。在只读式编码流程中运行是安全的。
为仓库完成引导设置——构建图、安装 git 钩子、注册 Agent 集成(AGENTS.md 区块、MCP),并以 doctor 报告收尾:
./target/release/sinter init /path/to/repo
Init 会按作用域分组,打印所有即将写入的内容,并在写入前统一询问一次(-y 跳过提示;非交互式运行会打印计划并继续)。所有写入都在仓库内进行——除非传入 --global,否则不会触碰 ~/.claude;传入该选项会添加机器级技能卡和强制执行钩子。当仓库是 git 工作树且现有行未涵盖 .sinter/ 时,init 和 ensure 都会将 .sinter/ 追加到根目录的 .gitignore。
仓库本地的 Claude 钩子采用有界严格强制机制:会话中首次进行宽泛递归搜索时,会将其重定向到 Sinter;重试时则允许继续,并提醒使用备用搜索。通过 --global 安装的机器级钩子仍仅提供建议。
在终端中,init 会在运行编译器索引器(sinter scip)前征求同意,因为这些工具链会执行仓库构建脚本;传入 --scip 或 --no-scip 可预先作出选择(非交互式 init 会跳过这些索引器)。
此后,每次查询都会在查询边界自动同步——没有变化时,同步只会遍历文件状态(不读取文件,也不执行写入事务)——而 git 钩子会在提交时主动刷新;sinter build 仍可用于 CI 和脚本编写。也可以从任意子目录运行命令,发现图根目录的方式与 git 相同。构建报告会分别显示启发式方法的锚定漏检率和相对于编译器的准确率。没有 SCIP 时,锚定率仍有参考价值,但它不代表召回率:启发式方法可能会将编译器可解析的引用判定为外部引用。
resolution (this pass): ... resolved (scip 0, import 118, scope 189), ... unresolved (105 internal, 3193 external)
anchored miss rate (this pass): 25.5% (heuristic classification, not compiler-relative recall)
存在 SCIP 索引时,报告还会打印编译器交叉校验结果(内部绑定的引用中有多少比例与编译器一致),以及相对于编译器的内部召回率(没有 SCIP 时,sinter 找到了多少个编译器绑定的引用)。自索引构建后有过编辑的文件完全没有 SCIP 证据——其中的引用会回退到导入和作用域解析,而不会按字节位置重新绑定——因此,过时的索引绝不会把调用归到当前行上已不存在的名称。语法解析器只能部分解析的文件会计入一行构建统计中(N parsed partially (M symbols in them; …));sinter doctor --verbose 会列出这些文件。
先了解概况,再搜索,这样下一个查询就能使用仓库自己的模块和符号词汇:
sinter map /path/to/repo
这份映射是初步清单。如果目标还只是一个概念,而不是已知符号,接下来请使用 ask。
针对图谱提问(输出示例来自此仓库):
$ sinter ask "where is the trigram search"
1. function Store::search [doc+name+path+sig 2/2 terms]
crates/sinter-store/src/search.rs:148
/// Fuzzy candidates: nodes sharing the most trigrams with the query,
pub fn search(&self, query: &str, limit: usize) -> Result<Vec<Node>, StoreError>
ask 是经过校准的词汇导航器,因此应将其命中项视为待检查的位置,而非生成的答案。每个命中项都会显示匹配来源,文本卡片还会根据排名第一的命中项证据给出一行置信度(confidence: high — verify top hit);若排名第一的命中项较弱,则标为 unrated。与问题匹配的字符串字面量会列在符号命中项之后;在证据相同的情况下,夹具、示例和测试局部定义的排名低于生产代码定义。
Agent JSON 会按主题分组结果,并严格限制结果总数,同时让每个命中项保持精简:排名、名称、类型、文件、行号、签名、文档、匹配词、通道和一个词的置信度。--explain(文本或 JSON)会补充排名差距、查询词覆盖率、具名留出校准信息和逐项评分。查询词会通过一个小型同义词表扩展(cap、limit、budget;size、bytes;caller、dependent),但权重较低,因此字面匹配始终优先于同义词匹配。对于较弱的单项结果、较低的查询词覆盖率,以及采样不足的排名差距区间,系统会放弃作答。CLI JSON 和 MCP structuredContent.data 使用相同的载荷。
每个 affected、deps 和 path 响应都刻意限制了范围。deps 默认深度为 1(可用 --max-depth 扩大)。affected 会在枢纽处停止(入度超过 100,或种子节点的直接调用者超过 50 个),并说明停止原因(stopped at hub Store (fan-in 114); --through-hubs to continue)。两者都会统计测试作用域的行数,而不列出它们(--include-tests);--relations calls,uses 会移除文件级导入行。path -k N 最多返回 N 条节点不相交路径;若无匹配项,则会打印最接近的前沿、筛选器排除的边、由筛选器导致时的 reason: filter_excluded,以及可运行的重试命令。在 --json 中,肯定和否定答案都包含 coverage 摘要(完整性、是否有定论、快照、编译器索引状态);--coverage 会恢复仓库级概览,其中包含证据来源、确定和可能的结果数量、未解析引用数量以及明确列出的缺口。universe 字段会列出仓库根目录,或所有已声明且参与搜索的工作区成员。completeness 只描述已索引的快照,conclusive 仍为 false,因此 Agent 不会把非空的纯语法结果说成穷尽性结论。
面向 Agent 的节点 id 值是稳定的符号键,不会因无关的偏移变化而改变。snapshot_id 保留报告快照中精确到字节的定位信息。接受句柄的操作支持 if_snapshot,并会返回类型化的快照过期、句柄已迁移或候选项有歧义结果,而不会静默地重新绑定。若符号的名称本身有歧义,可使用 Name@file 或 Name@file:line 定位([email protected]:175)。
在真实代码仓库上测试 Sinter
Sinter 正在招募 10 位设计合作伙伴,他们会在依赖关系或影响范围调查成本高昂的代码仓库中使用编码 Agent。请带来一项真实任务。评估将比较使用和不使用 Sinter 时的调查情况,并记录图谱在哪些方面发挥了作用或未能奏效。
提交设计合作伙伴议题 以推荐一个公开代码仓库,或在不透露名称的情况下介绍一个私有代码仓库。请勿在议题中包含私有源代码、凭据或客户信息。
命令
| 命令 | 用途 |
|---|---|
sinter ensure [repo] | 仅构建或刷新派生图;不会安装钩子或修改 Agent/客户端配置 |
sinter map [repo] | 在陌生仓库中采取的首个操作:结构化模块清单、明确测量的依赖枢纽、文档入口,以及一行图健康状态(部分语法文件、用户缺口、编译器索引状态)(--json) |
sinter init [repo] | 为仓库完成引导:构建 + 钩子 + Agent 集成 + doctor。先显示计划并要求确认(-y 跳过)。默认限定于仓库;-g 还会在整台机器上安装技能卡和强制执行钩子(--scip/--no-scip 可预先回答是否同意使用索引器) |
sinter uninit [repo] | 完全移除:删除图和每个由 sinter 管理的项目(-g 还会删除全局技能和钩子) |
sinter build [repo] | 构建或增量刷新图 |
sinter watch [repo] | 根据文件系统事件持续更新图 |
sinter hooks install | 安装 Git 钩子,在提交/切换/合并后刷新 |
sinter ask "<question>" | 针对模糊问题提供经过校准的词法起点,并给出验证/弃答指引 |
sinter show <symbol> | 为符号或文件提供单屏导览卡:包含属性的签名、一行 used by: N files, M edges 统计(--callers 列出文件)、类型的 impls (N)(--impls 输出其主体)。--body 会在源码不超过 60 行时输出完整源码,否则尽可能按 --budget-bytes 输出;--context-lines 0 会强制输出整个范围。范围超过 8 KB 或 200 行时改为输出 outline (N),其中按行列出嵌套定义、用于区分字面值的分支以及命令/标志字面值(--outline 会对任意符号强制输出大纲;--body 输出源码)。show @file:line 会指出该行所属的符号;Name@file:line --body 会摘录该行附近内容,并以 > 标记。若名称匹配多个结果,则优先显示 resolved: Name@file,并列出同名干符号 also_see |
sinter query <symbol> | 精确 + 模糊符号搜索,优先显示生产代码副本;只有模糊邻近项匹配时以状态码 1 退出;Markdown 章节正文最多 200 个字符 |
sinter affected <symbol>... | 反向影响范围,可按证据筛选;多个种子会合并并去重,每行列出到达该项的种子。遇到枢纽时停止(--through-hubs 会继续),并统计测试行数(--include-tests 会列出测试行) |
sinter deps <symbol> | 正向影响范围:某符号依赖的内容,默认仅显示直接依赖(--max-depth N 可扩大范围) |
sinter unresolved | 列出未解析的引用,即图中如实呈现的缺口。各行列出用户缺口(应由语料定义的名称、悬空的 crate::x::gone 路径);外部引用、解析器缺口和不支持语法的引用会计数但隐藏(--all 会列出)。每页 50 行,使用 --cursor N 查看下一页;可用 --file、--name 筛选 |
sinter path <from> <to> | 显示带逐步证据的最短依赖路径;-k N 最多返回 N 条节点不相交的路径。若答案缺乏证据,则报告最近的边界、排除的边、reason(filter_excluded)以及建议的重试方式 |
sinter grep <regex> [--within <traversal>] | 在索引语料中进行正则表达式搜索。默认不设范围限制(搜索 --scope 中的每个文件;--no-tests 排除测试文件);使用 --within 'affected(SYM)'、deps(SYM)、file(PATH) 或 file(DIR)(目录下的每个索引文件)可限定范围;可重复指定并合并结果,且种子自身的文件始终包含在范围内。若范围没有匹配项,会发出警告,而不会静默返回空结果 |
sinter context "<task>" | 为编码任务生成证据包:编辑候选项、依赖项/依赖者、匹配的字面值和镜像项、可运行命令形式的相关测试、缺口、后续 sinter 命令(--workspace <manifest> 会汇总工作区成员的证据包) |
sinter assert no-callers <symbol> | 默认检查是否存在生产代码调用者;只有结果为 holds_for_indexed_snapshot 时才以状态码 0 退出,可通过 --scope、--workspace、--certain 和 --json 控制。若其他文件中存在同名干符号(also_see),不会静默择一;名称未知时以状态码 2 退出。JSON 格式紧凑(ignored_out_of_scope 内联显示);--verbose 会保留仓库级 coverage.graph 区块 |
sinter assert no-dependents <symbol> | 对常量、类型和 trait,按相同规则检查所有非包含关系(uses、reads、writes、implements 等);no-callers 只统计 calls 边 |
sinter assert deletable <symbol> | 列出所有范围中深度为 1 的依赖者,并按范围分组;存在依赖者时以状态码 1 退出(has_dependents),未发现时以状态码 0 退出(none_observed) |
sinter cite <symbol> | 输出相对于仓库根目录的 Markdown file#Lline 引用,并附带稳定的符号键 |
sinter verify-doc <file.md> | 重新解析受管理的引用;裸 path:line 引用即使位置存在也会返回 not_proven |
sinter impact <rev-range> | 变更的符号 → 影响范围 → 受影响的测试。验证命令优先显示;测试按与变更符号的距离排序,并按语言以可运行命令的形式输出(cargo test、go test -run、pytest、npx vitest run);影响范围中生产文件优先于测试框架文件。--expect <symbol> 会报告差异未触及的直接依赖者;--full 会同时恢复显示完整影响范围 |
sinter serve | 通过标准输入/输出运行 MCP 服务(使用 --repo 指定单个仓库,使用 --workspace <manifest> 指定跨仓库范围) |
sinter overlap <range>... | 将未合并的 PR 映射到图上;对两两合并风险排序(直接/范围/文件;--relations 用于选择范围层级所沿用的关系)。若一个范围包含另一个范围的端点,则报告为 sequential,不进行评分 |
sinter workspace <manifest> | 构建跨仓库工作区的所有成员,并刷新边界链接 |
sinter init --workspace | 写入工作区清单模板(绝不覆盖现有文件) |
sinter install [targets] | 写入 Agent 卡片(claude、cursor、agents/AGENTS.md、enforce(可使用 --strict)、all);--mcp 会为 Claude Code、Cursor 和 Codex 注册服务 |
sinter scip [repo] | 运行所有匹配的编译器索引器,合并到 .sinter/index.scip 并重新构建;索引为最新时不执行操作(--force 会重新索引);scip check 用于在 CI 中检查索引是否为最新。索引器输出写入 .sinter/scip-<lang>-<n>.log,终端中每个索引器显示一行摘要 |
sinter doctor [repo] | 诊断安装情况和图:汇总显示 integration: all N checks ok(或列出失败检查)、正在运行的不同版本的本仓库 sinter serve 进程(Linux)、部分语法文件数量(--verbose 会列出这些文件)、SQL 语法缺口和 schema lint;每项发现都会指出修复方式;--fix 会应用安全修复并显示重建进度 |
sinter update | 自行更新到最新版本,并验证校验和(--dry-run 仅报告更新内容) |
sinter completion <shell> | Shell 补全 |
sinter version | 版本、图 schema、语言包 |
MCP 注册使用可移植的 sinter 命令,并以非必需状态启动,因此缺少二进制文件不会阻止客户端启动。sinter doctor | |
会检查该命令是否能解析为 PATH 上的可执行文件,并执行 MCP | |
| 握手。 |
读取时会以共享锁打开图;重建时则持有独占锁。重建期间到达的查询最多排队两分钟,并在一秒后打印一条
waiting for another sinter process 提示,因此并行
Agent 遇到的是延迟,而非 Database already open 错误。已结束会话遗留的 MCP
服务会继续使用原来的二进制文件;版本不同时,每个服务都会以自己的格式重写图,因此 sinter doctor 会列出为此仓库提供服务的实例及其 pid。
affected、deps 和 path 接受 --evidence scip,import,scope,dynamic 和
--certain,用于将遍历限制在证据等级较高的范围内;还接受
--relations calls,uses,imports,implements,extends,reads,writes,creates,alters,drops
来限制要跟随的边关系(例如,排除文件级导入边,以缩小影响范围);sinter grep 的 --within
范围也接受相同的遍历筛选条件;对应的 MCP 工具接受相同的筛选参数:evidence(数组)、
min_confidence: "certain" 和 relations(数组)。
MCP 工具与 CLI 默认值一致:scope 为 CLI 语料库
(production,test,docs;ask 使用 production,docs),deps 的深度为 1,
affected 会在到达枢纽时停止。参数会根据公开的架构进行验证(tools/list 包含枚举值和单行说明),因此
max_depth: "two" 或 relations: "calls" 会返回 invalid_arguments,而非被静默忽略。每种可由用户修正的失败情况——未知符号、
名称有歧义、参数错误——都会返回一个 isError 工具结果,其
structuredContent.error 包含 code、message 和 Name@file
候选项;outcome.status(complete、partial、not_proven、
not_found、error)和 outcome.reason(limit_reached、
filter_excluded,等等)是唯一需要用于分支判断的字段。分页覆盖完整结果:limit: 0 表示不设上限,有剩余行时会设置 next_cursor,
cursor 用于继续读取。symbol 回显仅包含 key、name、file、line;除非设置 include_coverage: true,否则会省略 coverage 块。show、deps
和 affected 接受 symbols: [...],path 接受 pairs: [[from, to]],
每个条目返回一个结果。budget_bytes 小于最小答案所需大小时,会返回该答案并标记,而非报错;next_actions 是工具调用。
ask 默认使用 production,docs 语料库;其他所有动词默认使用 production,test,docs。使用 --scope 或 MCP 的 scope 数组来包含
fixture、示例、生成文件或供应商代码。精确的 show 不会进行筛选。仓库可以在 .sinterignore 中排除路径;使用 gitignore 语法的模式,在已提交的 .sinter.toml 或
.sinter/config.toml(本地配置,优先级更高)中对 fixture 语料进行分类并应用有序覆盖:
[scope]
fixture = ["worked/**", "tools/*/expected/**"]
[[scope.override]]
pattern = "tools/golden-production/**"
scope = "production"
未配置时,任何路径段名称为 fixture(s)、golden、
testdata、expected、worked 或 snapshot(s) 的路径都会被分类为 fixture,而名称为 example(s)、sample(s) 或 demo(s) 的路径会被分类为示例。
语言
Rust、Go、Python、TypeScript、JavaScript(ESM、CJS、JSX)、Java、C#、C、
C++(包括 Unreal Engine 宏约定)、SQL(DDL/DML)、Bash、
Protobuf、Starlark(Buck2/Bazel BUCK、BUILD、.bzl:defs、load() 边、
规则调用),以及 Markdown(标题会成为嵌套的章节节点,开篇段落作为文档,因此 sinter ask 能找到带有 file:line 来源信息的文档内容;[text](target) 链接会从链接所在章节向目标文件创建 uses 边;如果带有 #fragment,则指向标题 slug 化后与之对应的章节;仅当目标解析为语料库中的文件时才会创建:失效链接保持未解析状态,外部 URL 不会生成任何内容)。语言只是纯数据——一个 tree-sitter 语法、一条 .scm 捕获查询(以及一个可选的、在规格中声明的内联辅助语法)和一行规格,由一个从不按语言分支处理的引擎使用。添加一种语言无需修改引擎代码;如果确实需要修改,问题出在捕获约定,而不是语言本身。
仅基于语法的绑定涵盖以下各语言的情况:Python 的 import x as y 别名、函数局部的 from m import f 调用,以及嵌套 def 中的调用;TypeScript 的 new X() 构造函数调用、默认导出和 export * 桶形重新导出;Go 的接口实现通过跨包的方法集匹配(如果针对接口方法的 affected 无法遍历实现,会提示 gap: implementations not traversed)。
显式实现——Rust 的 impl Trait for T、Java、C# 和 TypeScript 的 implements、类继承——也会创建方法级别的 implements 边,因此 sinter affected Trait::method 会到达实现方法,而不只是 trait 方法的调用方。
一条边会保留它发现的所有调用点,最多八个,并附上真实总数:如果某个调用方两次调用同一符号,显示为 path/to/file.rs:12, :48;有多个调用点时,--json 会添加 sites 和 sites_total。图谱架构 v16 会携带这些信息;升级后,现有图谱会在首次查询时重建一次。
SQL 图
对于 .sql 文件,Sinter 会生成 table、view、column 和 index 节点。
它还会记录对象引用的方向和用途:
reads:SELECT、FROM或JOIN的源writes:INSERT、UPDATE或DELETE的目标creates、alters、drops:由 SQL 文件负责的架构变更uses:外键和索引依赖
视图拥有其定义查询中的读取关系。顶层语句归属于所在文件,包括迁移文件。
嵌入在 Rust 中的 SQL 也会被提取,但仅限已知查询调用点中的字面字符串:sqlx::query!/query_as!/query_scalar! 宏、sqlx::query* 和 diesel sql_query 函数,以及 tokio-postgres、rusqlite 和连接池的 query*、execute*、batch_execute 和 prepare* 方法。外围 Rust 函数会获得 reads/writes 边,因此表的影响范围可以跨越语言边界。表名首先在数据库根目录(包含迁移和查询的目录)内解析,然后回退到整个语料库中唯一的定义。
查找涉及某个表的所有查询、迁移和 Rust 函数:
sinter affected users --relations reads,writes,creates,alters,drops
证明索引快照中没有任何内容会写入、更改或删除某个表:
sinter assert no-writers users --json
检查某个迁移的数据和架构依赖:
sinter deps migrations/20260901_users.sql \
--relations reads,writes,uses,creates,alters,drops
sinter doctor 会按文件名顺序合并迁移,并在某个表已在当前版本中删除但仍被引用,或已被引用但从未创建时发出警告。
限制。SQL 语法(tree-sitter-sequel)无法解析若干 PostgreSQL 结构——CREATE FUNCTION/PROCEDURE/TRIGGER/POLICY、DO 块、行级安全。包含这些结构的文件会根据部分语法树建立索引:语法解析器丢弃的语句不会出现在图中,doctor 会用一行报告这一缺口,并指出可能涉及的结构。运行时构造的 SQL 字符串,以及嵌入在 Go、Python 或 TypeScript 中的 SQL,不会被提取。Sinter 不会推断列级血缘、事务范围、查询所需的索引或规划器行为;要获取规划器证据,请对目标数据库使用 EXPLAIN。
顶层的 graphify-out/、memory/ 和 .memory/ 会从语义语料库和 SCIP 新鲜度清单中排除。这些是派生的分析产物;若将它们编入索引,生成的摘要就会反过来影响 ask 和依赖关系查询的答案。
如果仓库根目录或 .sinter/index.scip 中存在编译器生成的 SCIP 索引(index.scip),sinter 会将其作为最高证据层摄取。sinter scip 会根据构建标记查找已配置的项目根目录,并且只运行 PATH 中可用的匹配索引器(rust-analyzer、scip-go、用于 TS 和 JS 的 scip-typescript、scip-python、用于 C/C++ 的 scip-clang、scip-java、scip-dotnet),将结果合并到 .sinter/index.scip,然后重新构建。没有项目标记的独立源文件和测试夹具不会触发仓库级索引器建议。Bash、proto、SQL 和 Markdown 没有 SCIP 索引器。
团队
图是按机器生成的,可在几秒内重建;SCIP 索引则是开销较大的共享产物。在 CI 中构建一次(sinter scip),分发该文件,每位队友的下一次构建都会自动摄取它。操作流程、缓存键指南和可直接复制粘贴的工作流:
docs/team.md。
准确性和性能以实测为准,而非口头宣称
- 黄金语料:经过人工验证的固定样例(撰写本文时为 82 个),涵盖全部十三种语言,取自真实世界的提取惯用模式。提取和解析都会在 CI 中针对列出的契约事实进行门控,精确率/召回率必须达到 1.0;任何导致指标变化的改动都会失败,并打印确切的缺失/多余元组。预期结果依据语言语义得出,绝不依据引擎输出(
harness/golden/)。 - 真实仓库评估:在 ripgrep(Rust)、Cobra(Go)、Flask(Python)、Hono(TypeScript)和 Gson(Java)的固定版本上运行 249 项人工标注的纯语法导航任务:3 项精确查找、166 个按意图标注并划分调优集/留出集的自然语言
ask问题、36 项直接调用者检查,以及 44 项路径检查。当前成绩单显示,ask的 top-1 准确率为 0.705(留出集为 0.696),MRR 为 0.810,recall@5 为 0.945,recall@10 为 0.986,p95 延迟为 55 ms。调用者检查的精确率为 1.000、召回率为 0.523,路径检查得分为 0.727:纯语法图无法识别编译器索引可以绑定的接收者类型调用和 Java 静态类调用,但测试框架仍会标注这些调用点。每周运行和手动触发的工作流会上传完整成绩单和纯语法构建计时结果(harness/eval/)。 - Agent 工作流评估:十八个确定性、无需联网的编码工作流,涵盖多步图使用、有界 Agent 响应、任务上下文,以及一道带标签的设计相似性问题;检查前必须先呈现两张现有映射表。 当前成绩单显示,9/9 个工作流和 21/21 个步骤均通过,其中有一次正确弃答,且零次不安全置信度失败。这些是观察性场景,并不代表一般性的端到端编码准确率。
- 预算(在约 2M 行 Go 代码的仓库上测量,包含 271k 个节点,早于基于 stat 的扫描落地):完整构建 18s,单文件编辑通常不到 1s,冷启动点查询不到 100ms,
ask端到端耗时 66ms。现在,干净同步仅进行 stat 遍历——不读取文件、不执行写事务——在此仓库上的耗时为 46→16ms,在 80MB/400 个文件的合成语料上的耗时为 55→10ms;旧的 2M 行代码仓库空操作 73ms 数据早于 stat 门控。冷启动和增量编辑预算由 CI 强制执行(crates/sinter-store/tests/cold_start.rs、crates/sinter-cli/tests/incremental_build.rs);完整构建、热查询和内存预算依据harness/perf/README.md手动测量。
工作区布局
| Crate | 职责 |
|---|---|
sinter-core | 类型化图模型;在构造时强制执行不变量 |
sinter-store | 嵌入式 redb 存储:邻接关系、搜索索引、增量派生 |
sinter-extract | 与语言无关的 tree-sitter 提取;以数据形式表示语言 |
sinter-resolve | 基于证据的引用解析 + SCIP 导入 |
sinter-cli | sinter 二进制文件:流水线、动词、MCP 服务 |
评论
一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。