内容
# Kalkan
**Kalkan**(土耳其语意为*盾牌*)是人工智能代理与文档之间的完整性层:代理只能*提出*结构化补丁 —— 确定性引擎验证它们,自动应用,记录每个版本,并在无需模型调用的情况下精确回滚。
## 问题
2026年4月,微软研究院发表了[**“LLMs Corrupt Your Documents When You Delegate”**](https://arxiv.org/abs/2604.15597) (Philippe Laban, Tobias Schnabel, Jennifer Neville),推出了 **DELEGATE-52** 基准测试:19个大型语言模型(LLM)在52个专业领域编辑文档,每个会话包含10次编辑/恢复循环。即使是最先进的模型也在长时间委托会话中损坏了约四分之一的文档内容 —— 而且这种损坏往往是无声的:代理报告成功,而文件却悄悄地丢失行、词句和结构。Kalkan解决了这种失败模式的根本原因:它完全将模型从写入路径中移除。
## 结果
使用我们的DELEGATE风格的测试框架 —— 6个文档 × 10次编辑+恢复对(每次20次交互),在三种条件下进行,Claude Sonnet通过`claude -p`调用。完整表格见`eval/RAPOR-sonnet-k2.md`。
<!-- 占位符将在运行k2完成后从eval/RAPOR-sonnet-k2.md填充;有关确切的单元格映射,请参见lansman/placeholder-envanteri.md。 -->
| 条件 | 最终相似度(平均值,1表示完整) | 未触及区域损坏率(平均值) | 允许区域残留漂移率(平均值) | 灾难性事件 |
|---|---|---|---|---|
| **A1 — 完全重写** (粘贴文档,请求编辑副本) | 0.7381 | 30.38 | 25.61 | 4 |
| **A2 — 普通文件工具** (`read_lines` + `str_replace`,无验证) | 0.9946 | 0.00 | 5.98 | 0 |
| **B — Kalkan** (验证补丁 + 版本回滚) | 1.0000 | 0.00 | 0.00 | 0 |
诚实说明:普通文件工具(A2)在大多数情况下表现良好,但没有保证 —— 其最差的运行结果为0.9823的最终相似度,而*允许区域残留漂移*指标专门用于捕获其失败恢复在编辑区域内留下的内容。
## 工作原理
四个部分,全部确定性:
1. **MCP工具集** —— 六个通过stdio的工具(`open_document`、`read_section`、`propose_patch`、`list_versions`、`revert`、`get_report`)。读取是分窗的(每次调用最多200行,刻意不进行完整文档转储);`propose_patch`是*唯一*的写入路径。
2. **补丁引擎** —— 纯TypeScript,无模型,无文件系统。每个操作(`replace` / `insert_after` / `delete_section`)必须锚定在**恰好一次**出现的文本上;模糊或缺失的锚点会被拒绝,并提供最接近的匹配段落及其行号,以便代理自我纠正。重叠操作按名称拒绝;单个补丁不得触及文档的40%以上(爆炸半径上限)。补丁列表要么全部应用,要么全部不应用。
3. **版本存储** —— 文档旁边隐藏的`.kalkan/`文件夹保存每个版本的完整副本以及清单(id、时间戳、操作摘要、代理理由)。无需git依赖。`revert`以**字节精确**的文件操作方式恢复版本 —— 模型从不重新生成“恢复”的内容。
4. **差异和会话报告** —— 每次拒绝都有可行的原因;`get_report`总结补丁、拒绝、更改的行范围和版本计数,以便您可以审计代理实际执行的操作。
```mermaid
flowchart LR
A[AI代理] -->|MCP / stdio| T[Kalkan工具集]
T --> P[补丁引擎<br/>精确锚点、重叠检查、<br/>爆炸半径上限、原子应用]
P -->|验证写入| D[(document.md)]
P -->|快照每个版本| V[(.kalkan/ 版本存储)]
V -->|回滚:字节精确恢复,<br/>无需模型调用| D
T --> R[差异/会话报告]
```
## 快速入门
```bash
npm install
npm run build # 编译到dist/
npm test # vitest套件
```
### Claude Desktop
添加到`claude_desktop_config.json`(调整路径):
```json
{
"mcpServers": {
"kalkan": {
"command": "node",
"args": ["C:/path/to/kalkan/dist/index.js"]
}
}
}
```
### Claude 代码
```bash
claude mcp add kalkan -- node /path/to/kalkan/dist/index.js
```
或在`.mcp.json`中限定于项目范围:
```json
{
"mcpServers": {
"kalkan": {
"command": "node",
"args": ["./dist/index.js"]
}
}
}
```
### 3分钟快速体验
`ornek/ornek-belge.md`中提供了一个示例文档。尝试与您的代理进行此对话:
1. **打开** — "使用kalkan打开`ornek/ornek-belge.md`。" → 元数据到达;`.kalkan/`现在保存`v0`。
2. **补丁** — "在İletişim部分,将联系方式更改为提及电子邮件,并附上理由。" → 确定性应用,保存`v1`。
3. **故意失败** — "替换句子'此文本不存在'。" → 原子拒绝;错误建议最接近的实际段落;文件在字节上与之前相同。
4. **回滚** — "回滚到v0。" → 文档在字节上与`v0`相同;恢复本身记录为`v2`。
5. **审计** — "获取会话报告。" → 1个补丁,1个拒绝及其原因,3个版本。
## 测量
完整方法见[`eval/METHODOLOGY.md`](eval/METHODOLOGY.md)。简而言之:每个条件运行**相同的文档、相同的指令、相同的顺序** —— 每个文档10次编辑+恢复对,每次交互都是全新的对话。**A1**粘贴文档并请求完整编辑后的副本(无保护基线)。**A2**为模型提供未经验证的`read_lines`/`str_replace`文件工具 —— 今日典型的代理设置。**B**为其提供Kalkan的工具,其中恢复是版本恢复而不是模型输出。指标基于行-LCS,并完全确定:与原始文档的最终相似度、未触及区域的损坏、允许区域内的残留漂移(失败恢复)以及灾难计数(>10%的文档在单个交互中更改)。
自行复制:
```bash
npm run eval:pilot # 1个文档 × 3轮 × 3个条件,事先确认
npm run eval:full # 完整运行:6个文档 × 10轮 × 3个条件
npm run eval:report # 从结果JSON重新生成eval/RAPOR-<model>[-<label>].md
```
测试框架在您安装的Claude Code订阅(`claude -p`,无需API密钥)或Anthropic API(`eval/config.json` → `saglayici`)上运行。结果作为原始JSON存放在`eval/sonuclar/`中 —— 包括每个模型响应原样 —— 因此报告中的每个数字都可以被审计。如果您使用不同的模型或提供商运行它,我们很乐意看到您的`RAPOR-*.md`(请参见[CONTRIBUTING.md](CONTRIBUTING.md))。
## 已知限制和路线图
- **整个文档补丁有上限,不是按范围划分** —— 单个操作触及文档的>40%会被拒绝,但更细致的*爆炸半径强制*(按章节范围)是v2。
- **目前没有语义不变性** —— Kalkan保护结构和未触及的区域;诸如“总数必须保持一致”的规则是v2。
- **仅限Markdown / 纯文本** —— 无DOCX,无电子表格,无代码感知补丁。
- **单模型测量** —— 已发布的数字是单个模型在六个土耳其文档上的结果;测试框架支持使用其他模型重新运行,跨模型结果正是我们希望的贡献。
- v2顺序将遵循社区反馈 —— 如果其中一个阻碍了您,请提出问题。
## 贡献和许可
参见[CONTRIBUTING.md](CONTRIBUTING.md) —— 欢迎提出错误报告、补丁引擎边缘情况,*尤其是*您自己的测量运行。遵循[MIT](LICENSE)许可。