Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

14 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

docmap — 文档图谱 × agent 阅读遥测

一句话:codegraph 让 agent 不必自己理清代码关系;docmap 让 agent 不必自己摸索该读哪份文档,并且把"文档被读了多少次、烧了多少 token、有没有读到过期结论"量出来。

对任何 Markdown repo 都能建图;Claude Code 可零配置采集,其他 Agent 通过标准 JSON/NDJSON 事件流接入。绝不往目标仓库写任何文件(缓存全落 ~/.cache/docmap/<slug>/)——这样目标仓库能当对照组。

bin/docmap --repo ~/repo build      # 建图 + 采遥测 + 标定 token 系数
bin/docmap --repo ~/repo report     # 九类诊断(人看)
bin/docmap --repo ~/repo serve      # 图谱(浏览器画布,实时)
bin/docmap --repo ~/repo route "更新 API 鉴权"       # 该读哪几份(agent 用)
bin/docmap --repo ~/repo plan-change "更新发布状态"  # 新建/插入/修改?
bin/docmap --repo ~/repo impact src/auth              # 哪些文档需要复核?
bin/docmap --repo ~/repo validate                     # 检查当前 Git diff
bin/docmap --repo ~/repo baseline                     # 历史任务的阅读成本基线

python3 docmap.py …python3 -m docmap …pip install -e . 后的 docmap … 三种入口等价。核心零依赖;只有读 profile 需要 pyyaml

它和已有的东西差在哪

做什么 缺什么
Obsidian graph 画链接图 不知道谁读过、花了多少;表达不了"谁推翻了谁"
token-dashboard 等 算 token 成本、文件热力 不知道文档之间的关系,给不出"该读/别读"
codegraph 代码知识图 不管文档
docmap 图 × 遥测交叉

三族边

文档之间的关系有三种来源,它们打架的地方就是文档该重组的地方

来源 说的是
structure / tree 目录(纯路径推导,免费) 当初怎么归类的。每个目录一簇,簇心=该目录 README/index(没有就取 git 改动最多的),簇心辐射同目录成员、子簇心串父簇心
link / index / supersedes markdown 链接、裸路径、wikilink 作者觉得该连什么
coread 遥测:同 session 前后脚被读 实际上要一起读。判据用共现的 session 数而非原始次数——同一 session 来回翻会把次数刷高,但只是一次工作

九类诊断

诊断 抓什么 为什么贵
🔴 stale_read 文档带勘误,但 agent 跳读时没覆盖到勘误行 拿走的是已作废结论,而且它自己不知道
🔴 zombie 已整篇作废,却仍在被读 错误结论直接污染判断
🔵 mismatch 三族边打架:隐形依赖 / 松散目录 目录结构和实际用法对不上
🟠 fat 高读取 × 高 token 成本集中在少数几份,拆了立刻省
⚪️ cold 在库里、零读取 出库候选(比"没人提及"的 orphan 判据强)
🟡 route_miss session 开头连读多份才动手 入口没指准,每次都白花开场 token
📏 drift 同一冻结数字散落多处 改一处别处不同步
🧭 entry_gap 声明入口 vs 实测首读 索引写了没人走
📦 ext Agent 反复读取 repo 外文件 活知识没有被项目正式收编

文档变更闭环

docmap 不代替 Git 或 Agent 写文件。它在编辑前给出依据,在编辑后验证依赖:

# 1. 现有文档是否能承接?应该新建、插入还是修改?(只读)
bin/docmap --repo ~/repo plan-change "更新 API 发布状态"

# 已知目标时消除模糊匹配
bin/docmap --repo ~/repo plan-change "更新发布状态" --target docs/api/STATUS.md

# 2. 修改一个文档或 repo 路径会触及谁?(只读)
bin/docmap --repo ~/repo impact docs/api/STATUS.md
bin/docmap --repo ~/repo impact src/auth

# 3. Agent 正常编辑后,检查整个工作树的 Git diff
bin/docmap --repo ~/repo validate
bin/docmap --repo ~/repo validate --staged
bin/docmap --repo ~/repo validate --strict   # CI 可选择让 warning 也失败

validate 只让确定性问题默认失败:新文档缺职责/scope、断链、显式 repo 锚点 不存在、doc_id/canonical_for 冲突、继续引用已整篇作废的文档。代码变化触及 文档 scope、重文档和弱关系只报 warning;它们表示“需要复核”,不冒充语义漂移。

新文档可用最小 front matter 声明强关系:

---
doc_id: api-release-status
doc_type: status
scope:
  - src/auth
canonical_for:
  - api_release_status
depends_on:
  - docs/architecture/AUTH.md
owner: platform
status: gated
---

旧文档无需一次性补齐。治理门槛只强制作用于新增文档;现有文档可以按真实使用 热度渐进补元数据。所有命令支持 --json,便于以后封装成少量 MCP tools。

serve — 图谱

bin/docmap --repo ~/repo serve                              # 盯实时
bin/docmap --repo ~/repo serve --replay busiest --speed 60  # 回放,零 token

页面提供两个互补视角:

  • 文档关系:分别开关显式引用/依赖、目录结构、历史共读,避免把不同置信度的边混成一类。
  • Agent 阅读流:按每个 Agent 自己的时间顺序画有向箭头;右侧保留可访问的事件列表,避免把并行 Agent 之间的相邻时间误画成因果关系。
  • 灰点是本次未读,黑点是本次已读;红/黄色边框同时用状态文字表达作废或勘误,不只依赖颜色。
  • 点击节点查看入链、出链、共读伙伴、历史读取成本和诊断;支持搜索、关系筛选、拖拽、缩放与 F 全图定位。
  • 超过 450 个节点时保留目录预布局但跳过二次方力导向;关系超过 7000 条时明确提示并限绘,避免大仓库把浏览器主线程拖死。

页面自包含无外部依赖(离线可用),只监听 127.0.0.1

watch — 终端

bin/docmap --repo ~/repo watch          # 字符星图
bin/docmap --repo ~/repo watch --plain  # 纯文本流(可管道 / 无 TTY)
bin/docmap --repo ~/repo watch --sessions   # 列出可回放的 session

stream — 给别的宿主接

bin/docmap --repo ~/repo stream | jq -c 'select(.type=="read")'

先一行 {"type":"graph",…},之后每次阅读一行 {"type":"read",…}。VS Code / Cursor 扩展将来就是起这个子进程、把 stdout 转给 webview——Python 侧一行不用改,扩展只做一层薄壳。

token 怎么算的(不是拍脑袋)

message.usage 给出每步 context 总量;相邻两回合之差减去上一回合 output = 这中间读进来的量。取"该回合的 tool_result 全是文档读、且消息没挂别的内容块"的干净样本,对 (CJK 字数, 其余字数, 常数) 做三参最小二乘。

本仓实测:CJK 1.46 tok/字、其余 0.657 tok/字,中位相对误差 14%(n=2002)。中英密度差 2.2 倍,用单一常数必错。

三个必踩的坑写在 docmap/telemetry.py 顶部:同回合多行共享 usage(按 requestId 去重)、并行 Read 共享同一增量(按回合汇总回归)、无截距会把固定开销摊进斜率。第四个坑在 collect():增量运行样本远少于全量,拟合更差时不许覆盖已有标定,否则 token 口径每次 build 都漂。

数据来源与通用事件协议

Claude Code 适配器(零配置)

~/.claude/projects/<slug>/ 下三类 jsonl,三类都要收,少一类就低估成本:

<sid>.jsonl                                     主驾
<sid>/subagents/agent-*.jsonl                   Agent 子 agent
<sid>/subagents/workflows/<wf>/agent-*.jsonl    Workflow 扇出

Read 走精确路径与行窗口;Grep/Glob/Bash(cat/head/sed/grep)也计入,但 Bash 一次摸多个文件时按份数均摊 token,是近似值。

其他 Agent(canonical NDJSON)

核心图谱和 UI 不依赖 Claude。任何 Agent、IDE 或 MCP 宿主都可以逐行输出以下事件:

{"type":"prompt","provider":"my-agent","session":"s1","ts":"2026-08-12T10:00:00Z","text":"了解鉴权模块"}
{"type":"read","provider":"my-agent","session":"s1","agent":"main","ts":"2026-08-12T10:00:01Z","path":"docs/auth.md","tokens":420,"partial":false}
{"type":"action","provider":"my-agent","session":"s1","ts":"2026-08-12T10:00:03Z","kind":"edit_source","path":"src/auth.py"}
bin/docmap --repo ~/repo --events /tmp/agent-events.ndjson serve --speed 60
bin/docmap --repo ~/repo --events /tmp/agent-events.ndjson baseline

最小可视化事件只需要 type=readpathsessionprompt/action 用于 baseline。tokens 缺失时保留为未知成本 0,工具不会伪造精度。当前 canonical 文件按已录事件自动回放;真正的跨宿主实时流将在 MCP transport 层复用同一 schema。

怎么测(不花 token)

历史行为 baseline

baseline 把 transcript 按真实的人类 prompt 切成 task episode,再按 profile 中 可审计的关键词规则分类。它同时统计文档读取数、估算 token、重复/整份读取、首次工作 前阅读量、编辑与验证动作,并明确区分:

  • cold_start:该 transcript 的第一个用户请求;
  • warm_followup:已经继承当前 transcript 上下文的追问。

两类不能混成等价样本。Session 也不能直接当任务:真实 session 可能跨很多天、包含 多个用户目标。

bin/docmap --repo ~/repo --profile ./docmap.yml baseline
bin/docmap --repo ~/repo --profile ./docmap.yml baseline \
  --scenario onboarding --include-episodes --json

关键词命中只是历史样本初筛,不是任务真值;时间戳是可观测工具活动,不是人的注意 时间;Write 调用也不能证明文件最终落盘。准确率和任务成功率不在 transcript 中, 必须另做固定 prompt、人工评分的 A/B 实验。

数据边界:为了允许 profile 动态重分类,本地 telemetry cache 会保留每个真实用户 prompt 的前 4000 字;动作只保留类别、工具名和路径,不复制 shell 命令或编辑正文。 缓存仍在 ~/.cache/docmap/,权限设为仅当前用户读写。这是本地分析数据,不是 Agent 长期记忆;如仓库涉及敏感请求,应把该缓存纳入本机数据清理策略。

回放与模拟

看效果 → 回放。 已录的 transcript 里躺着几千次真实阅读,纯读盘重放:

bin/docmap --repo ~/repo watch --sessions
bin/docmap --repo ~/repo serve --replay busiest --speed 60

测实时通路 → 模拟器。 造一份假的"正在跑"的 session(含子 agent),只读目标仓库的文档当素材,不写它一个字节:

python3 tools/simulate.py --repo ~/repo --interval 1.5              # 终端 A
bin/docmap --repo ~/repo --transcripts /tmp/docmap-sim serve        # 终端 B

测试

python3 tests/test_units.py        # 分层用例,每个对应一次真实事故或统计口径
python3 tests/test_end_to_end.py   # 临时仓库 + 人造 transcript 全链

端到端那个额外验证一件事:目标仓库零改动

配置

零配置能跑(track 按目录推断、入口自动认 CLAUDE.md/AGENTS.md/各级 README)。要覆盖就写 profile:

bin/docmap --repo ~/repo --profile ./docmap.yml report

profiles/kmc.yml 只是大型科研仓库的验收样例,不属于核心默认逻辑。

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages