在拜读deepseek-harness这个仓库的过程中,我特意去看了deepseek团队有意(又或者无意)上传的.agents目录,其中有个skill名字叫dsh-trim-cot-leakage引起了我的注意。本文就从这个skill开始,我们看看deepseek工程团队是如何进行agentic coding的。
什么是 CoT Leakage(思考过程泄露)
CoT(Chain-of-Thought)leakage = 写出来的文字,视角是"作者工作现场"(作者的 session),而不是"仓库 HEAD 状态"。 读者必须"当时在场"------看过那次会话的 transcript、PR 讨论、未提交草稿------才能解析其中的引用、验证其中的断言。翻译成人话就是"能不能通过这些信息推断出当时会话做的决策,如果不能,那么就算是cot leakage"。
出处与权威定义:.agents/skills/dsh-trim-cot-leakage/SKILL.md(2026-08 全仓清理后沉淀为正式技能);分类法的校准例子见同一目录下 references/examples.md。
1. 背景:.agents/ 目录里有什么
仓库的 .agents/ 下只有两样东西:
notes/--- Agent Notes 决策档案库 :给 AI agent 用的决策记录,路径编码{生命周期}/{类别}/yyyy-mm-dd-主题.md。生命周期:proposed(提案)/implemented(已落地,保持与现状同步)/rejected(被否)/archived(冻结归档)。类别:architecture/feature/bug-fix/simplification/process/testing。记录的是"为什么 + 放弃了什么"------代码和文档承载不了的部分。skills/--- 操作规程:教 agent 怎么在这个仓库干活的程序化指令(SKILL.md = frontmatter 触发条件 + 步骤/标准/检查表)。
两者的关系分三种:直接管理 notes 的(dsh-archive-agent-notes、dsh-find-simplifications、dsh-trim-cot-leakage)、引用 notes 做标准的(多数技能正文会先让你读 notes 契约)、与 notes 无关的独立操作(dsh-pre-push-checks、dsh-code-review 等)。
一句话:notes = 仓库的"长期记忆"(决策的 why,跨会话可查);skills = "操作规程"(怎么干活的标准流程) 。agent 每次会话都是失忆重来,两者互为支撑,让工作有据可依、风格统一。
2. 为什么会发生
Agent Notes 的写作者就是 agent 本身 。agent 在会话里工作时有自己的内部产物:决策编号(decision 21)、审计编号(audit R3)、计划阶段标签(T4 / P-I / W3)、草稿章节号(§4.7)、草稿版本号(v5)、写给 reviewer 的辩护。这些产物只存在于会话里,从未提交进仓库。agent 写注释、JSDoc、笔记时天然带着自己的视角,私语就漏进了公开文本。
3. 核心判据:一个测试
一个只看到 HEAD、没有 会话 transcript、没有 PR 讨论、没有未提交草稿的读者,能否解析每一个引用、验证每一个断言?
两条可机械检查的问句:
- 可解析(resolvable) ------
decision 21、audit R3、§4.7在 HEAD 里找不到任何指称对象 - 可验证(verifiable) ------"used to double-encode" 这个断言,HEAD 代码里没有证据
注意:语义自明 ≠ 不是泄露 。Rendering is pure: same snapshot, same string (audit R3) 不需要任何上下文就能看懂,但 (audit R3) 在仓库里不存在------它依然被判为泄露,因为那是会话内部产物的残留。判据不问"读者能不能懂",只问"引用的东西在不在仓库里"。
4. 八类分类法
| # | 形态 | 泄露版 → 修复版 |
|---|---|---|
| 1 | 死掉的会话内引用 :(decision 7)、(audit C2)、设计稿 §4.7、阶段标签 |
"...(decision 21)" → 有归属则指向已提交的 owning note(名字 + 路径);无归属则删引用、把事实子句重述为独立陈述 |
| 2 | stack/PR 视角:"a later PR in this stack"、"this PR adds"、"the previous commit" | → 陈述扩展点/当前机制本身("A remote backend can implement this interface without changing the render layer.") |
| 3 | 变更叙事 + 版本戳:"used to"、"no longer"、"the old X"、"this cut"、"v1"、"today" | → 陈述当前行为;固定掉的回归写成现在时反事实("Without the byte-length guard, multibyte labels double-encode."),永不写仓库考古("used to Y") |
| 4 | 评审编排:"Rejected in review:"、"the reviewer confirmed"、"as of v5 of this note" | → 决策和理由变纯事实;评审者、轮次不进 rationale。合法居所:Agent Note 的 Alternatives considered 槽位 |
| 5 | 向 reviewer 辩护:"The cast is safe --- it simply..."、"This is correct because..." | → 陈述维护者不能破坏的不变量;若代码已可见则整条注释删除 |
| 6 | 复述/推导转录:"First we X, then we Y"、测试走查、显然分支的证明 | → 整段删除,只留非显然的契约或不变量 |
| 7 | 含糊话与计划残留:"Probably fine for now"、"should be enough" | → 升级为 TODO(name): 标记,或重述成实际边界 + 超界失败行为 |
| 8 | 语言滑移:英文正文混入"端"、"设计稿"、"---- 私有 ----" 分隔线 | → 翻译或删除 |
(完整例子库在 references/examples.md------它刻意引用泄露原文作校准材料,这些文字不是别处的写作许可。)
5. 修复原则:按命题重述,删转录
修复从来不是删除本身 。一句话往往一半是承重事实、一半是会话转录,要按命题(proposition) 拆开:事实重述 成 HEAD 视角的独立陈述(让它脱离上下文也成立),转录外壳删除------"删子句,不删整句"。
过度纠正陷阱(2026-08 清理本身被 review 抓出的四种错误,见 examples.md):
- 义务翻成背书 :"These direct registrations are exceptions pending migration to slots." 被删成 "sanctioned exceptions"------"待迁移"是义务,"被认可"是祝福现状,删短一句话把模态词翻反了
- 假设升格成已发布 :"A future IPC-based shell subclasses..." 删掉 future 就变成"该类已发布"------必须显式标"no such shell exists"
- 删事实带走了同行转录 :一句话前半是叙事、后半是承重耦合("the notice text is what
verify-doc-typecheckcompiles against"),整句删就把耦合也删了 - 保留数字丢了 provenance :"The 4 MiB ceiling is measured: the largest generated module is 3.1 MiB."------删掉 "measured",数字从观测变成定义,没人会再实测
6. 两层判定:证据 vs 体裁(判据只是一关)
判据之外还有第二个独立规则。两个正交的轴:
- 规则 A(证据/泄漏,本技能) :引用在 HEAD 可解析、断言可验证吗?失败 = 会话私语。全表面通用------死引用在任何表面上都不合法,README 不行、Agent Note 也不行。
- 规则 B(体裁/表面契约,dsh-prose-standard) :这句话的体裁和所在表面的契约匹配吗?表面相关------同一句话在这个表面违规、在那个表面合法。
| 表面 | 契约(只讲什么) |
|---|---|
| README / JSDoc / docs | 当前状态 |
| Agent Note | 决策 + 变化故事(已合并 PR 可作证据) |
| 代码注释 | 不变量/契约 |
走查一遍(同一句的两种变体):
"Colors used to come from
--widget-*tokens, which nothing defined, so it always rendered the fallbacks; the alias tokens fixed that (PR #88) ."
- 规则 A:PR #88 在 GitHub 上可解析,整个故事可验证 → 不是泄漏 ✓ 通过
- 规则 B:它躺在一份 README 里------当前状态面上叙述变更 → 变更叙事,仍然违规 ✗
- 修复:重述为 "Colors come from the alias tokens; an undefined token renders the fallbacks.";故事本身(如值得留)搬去 Agent Note 的 change-story 段落
去掉 PR 号的版本:"Colors used to come from --widget-* tokens..."(无任何引用)→ 规则 A 也失败------没有任何 artifact 支撑"曾经"这个断言 → 是泄漏(class 3)。
两句都要修,罪名不同:一句是"引用死了"(规则 A 失败),一句是"引用活着,但在错误的地面上讲故事"(规则 B 失败)。
关键结论:通过泄漏判据 ≠ 可以原样保留。 判据是"负向过滤器"------只回答"这算不算会话私语",不回答"这能不能留";当前状态面上的姿态规则(以及表面路由规则)在第二关等着。
7. 反向清单:长得像泄露但必须保留
- issue 引用 (
#1470、"issue #N owns the follow-up")------HEAD 可解析,任何表面上合法(曾有人误删,被 review 纠回:"删除可靠引用"和"保留死引用"两个方向的误杀都出现过) - 抑制理由 ------
oxlint-disable ... -- reason、覆盖率忽略原因、空 catch 的解释,是必需散文;理由写错了要改理由,永不删除 - "measured" 标记------provenance 词承重,标定常量的数据区别于猜测
- 运行时 old/new------"the old connection drains before the new one accepts" 命名的是交接中的两个运行时对象,不是仓库状态
- 外部标准------RFC 9110 §10.1.5 在仓库外可解析,§禁令只针对未提交的内部草稿;已提交且自有 § 编号的文档也可按节引用
- 项目 voice 与体裁形式------"we" 作为项目口吻;Agent Note 的 Alternatives considered 槽位里的 "rejected"
- Agent Note change-story 段落里的历史舞台名------"the first cut shipped X" 在那里是当前状态安全写法;但索引戳("this cut")在任何地方都禁止
8. 探针:recall-batteries 长什么样
技能目录 references/recall-batteries.md 提供一组 rg 探针,2026-08 清理时调校:
English battery(7 条):
css
rg -n --hidden '(decision \d|(audit [A-Z]\d|design §|plan §|design ledger|(B ruling|\bP-I\b|\bW\d\b|\bT\d\b' ... # 死引用
rg -n --hidden -i 'this PR|this branch|this stack|later PR|previous commit|this commit' ... # stack/PR 视角
rg -n --hidden -i 'used to |no longer|previously|the old |was renamed|was moved' ... # 变更叙事
rg -n --hidden -i '\bv1\b|this cut|\bcut \d|\btoday\b|\bfor now\b|roadmap' ... # 版本戳
rg -n --hidden -i 'rejected in review|review round|reviewer|as of v\d' ... # 评审编排
rg -n --hidden -i 'probably |should be enough|should suffice|it simply|is safe ---|is safe --' ... # 含糊话/辩护
rg -n --hidden '§\d' ... # 章节号
Chinese battery(2 条):
css
rg -n --hidden '设计稿|评审|上一?轮|旧版|老的|不再|以前|本版|遗留|私有' ...
rg -n --hidden '(^|[^a-zA-Z])端([^a-zA-Z]|$)' --glob '*.md' ...
(... 是公共参数:--glob '!vendor/**' --glob '!node_modules/**' --glob '!.agents/notes/archived/**' --glob '!.agents/skills/dsh-trim-cot-leakage/**' 加 fixture/快照目录;排除项必须放最后,免得后面的 include 又放回来。)
设计决策:
- 必须
--hidden------rg 默认跳过点开头目录,而本仓库最大的漏检风险恰恰是.agents/下的 Agent Notes -i只加在自然语言行 ------句子开头 "This PR adds..." 大写命中;代码模式行保持大小写敏感,否则\bT\d\b会误伤类型参数- 宁可过匹配------"every hit needs semantic judgment, the batteries over-match by design":探针是钓饵不是定义,命中后逐条人工语义判断
- 必然漏匹配------清理的每一轮 review 都发现了探针没抓到的案例,必须配合不带模式的人工通读(最密集的散文:模块 JSDoc、README、Agent Notes)
- 零命中 ≠ 安全------"A zero-hit pattern proves nothing until you have seen it match":没见过模式命中已知正例,就不能信任阴性结果
已知误报家族 (命中但合法保留):工具性的 "used to"("the key used to sign requests" = "用来"非"曾经")、运行时 old/new、讲 PR 流程的文档里的 "PR"、/v1/chat 协议路径(标识符非版本戳)、RFC §N 外部标准、"本版本"(合法)vs "本版"(违规戳)、Alternatives considered 槽位里的 "rejected"。
9. 为什么这个仓库需要它(以及对我们自己的启示)
这个仓库的纪律之所以显得夸张,是因为它的作者是失忆的 agent 集体:Agent Notes 是 agent 写的,JSDoc 是 agent 写的,prose 标准是给 agent 看的。而"笔记用会话私语写成"等于没记------决策的 why 又退回了一次性会话里。dsh-trim-cot-leakage 就是给这个作者群体照的一面镜子:一个测试 + 八类分类 + 保留清单 + 过度纠正陷阱,把"读起来像思维转录的散文"从玄学变成可机械执行的检查。
对个人笔记的启示:任何"跨会话的记忆"(Agent Notes、wiki、长期文档)都适用同一个测试------引用要可解析(写文件路径而不是"上次那个文件")、讲状态而不是讲叙事("我发现/我昨天")、把理解沉淀成事实而不是过程。不需要 gate 和 manifest,只需要那个"一个测试"在心里。
相关文档
.agents/skills/dsh-trim-cot-leakage/SKILL.md--- 技能本体(权威定义).agents/skills/dsh-trim-cot-leakage/references/examples.md--- 分类法例子 + 过度纠正陷阱.agents/skills/dsh-trim-cot-leakage/references/recall-batteries.md--- 探针全文 + 误报家族.agents/skills/dsh-prose-standard/SKILL.md--- 规则 B(current-state 规则)的归属技能.agents/notes/implemented/process/2026-08-09-committed-artifact-citations.md--- 引用规则(可解析性)的决策记录