
关于
为 Agent 提供代码库的持久结构记忆——导航依赖关系、追踪公共 API,并理解代码库的整体架构。
name: data-structure-protocol description: "为代理提供代码库的持久化结构记忆——导航依赖关系、追踪公共API、理解连接存在的原因,无需重新阅读整个仓库。" risk: safe source: "https://github.com/k-kolomeitsev/data-structure-protocol" date_added: "2026-02-27"
数据结构协议(DSP)
LLM编码代理在任务之间会丢失上下文。在大型代码库中,它们将大部分token花在"定位"上——弄清楚东西在哪里、什么依赖什么、什么可以安全修改。DSP通过将项目的结构映射外部化为存储在 .dsp/ 目录中的持久化可查询图来解决这个问题。
DSP不是给人类看的文档,也不是AST转储。它捕获三件事:含义(实体为何存在)、边界(它导入和暴露什么)、原因(每个连接为何存在)。这足以让代理在不将整个源代码树加载到上下文窗口的情况下进行导航、重构和生成代码。
何时使用
在以下情况使用此技能:
- 项目有
.dsp/目录(DSP已设置) - 用户要求设置DSP、引导或映射项目结构
- 在DSP追踪的项目中创建、修改或删除代码文件时(保持图更新)
- 导航项目结构、理解依赖关系或查找特定模块时
- 用户提到DSP、dsp-cli、
.dsp或结构映射时 - 在重构或依赖替换前执行影响分析时
核心概念
代码 = 图
DSP将代码库建模为有向图。节点是实体,边是导入和共享/导出。
两种实体类型:
- Object:任何非函数的"东西"(模块/文件/类/配置/资源/外部依赖)
- Function:导出的函数/方法/处理器/管道
通过UID标识,而非文件路径
每个实体获得稳定的UID:对象为 obj-<8hex>,函数为 func-<8hex>。文件路径是可变属性;UID在重命名、移动和重格式化后仍然存在。
对于文件内的实体,UID通过源代码中的注释标记锚定:
// @dsp func-7f3a9c12
export function calculateTotal(items) { ... }
# @dsp obj-e5f6g7h8
class UserService:
每个连接都有"原因"
记录导入时,DSP存储一个简短原因解释为什么该依赖存在。没有原因的依赖图告诉你什么导入什么;原因告诉你什么可以安全修改以及谁会受影响。
存储格式
每个实体在 .dsp/ 下有一个小目录:
.dsp/
├── TOC # 从根开始的所有实体UID有序列表
├── obj-a1b2c3d4/
│ ├── description # 源路径、类型、用途(1-3句)
│ ├── imports # 此实体依赖的UID(每行一个)
│ ├── shared # 公共API/导出实体的UID
│ └── exports/ # 反向索引:谁导入了这个以及为什么
└── func-7f3a9c12/
├── description
├── imports
└── exports/
一切都是纯文本。可diff。可审查。无需数据库。
完整导入覆盖
每个被导入的文件或制品都必须在 .dsp 中表示为Object——代码、图片、样式、配置、JSON、wasm等。外部依赖记录为 kind: external 但不分析其内部。
工作原理
初始设置
该技能依赖独立的Python CLI脚本 dsp-cli.py。如果项目中缺失,下载它:
curl -O https://raw.githubusercontent.com/k-kolomeitsev/data-structure-protocol/main/skills/data-structure-protocol/scripts/dsp-cli.py
需要 Python 3.10+。所有命令使用 python dsp-cli.py --root <project-root> <command>。
引导(初始映射)
如果 .dsp/ 为空,从根入口点通过DFS遍历项目:
- 识别根入口点(
package.jsonmain、框架入口、main.py等) - 记录根文件:为每个导出创建
create-object、create-function,为所有依赖添加add-import - 取第一个非外部导入,完整记录,深入其导入
- 无未访问本地导入时回溯;直到所有可达文件都被记录
- 外部依赖:
create-object --kind external,加入TOC,但不深入node_modules等
工作流规则
- 修改代码前:通过
search、find-by-source或read-toc找到受影响实体 - 修改代码后:更新受影响实体的描述、导入和导出
- 添加新文件:创建新实体,建立导入/导出关系
- 删除文件:移除实体,清理悬空引用