czm15053/write-notes-like-deepseek

write-notes-like-deepseek

Use when a change is non-trivial by DSH standards (behavior, architecture, cross-file contracts, process/tooling, testing strategy, or on-disk/wire/config formats), when choosing between technical alternatives, superseding a decision, or writing a postmortem.

View source
Original skill document

Rendered from the source repository. Headings, examples, code, tables, links, and referenced images are preserved.

Write Notes Like DeepSeek

方法提炼自 DeepSeek Harness 的工程实践。聊天里的 Agent 负责拆任务、排计划;本 Skill 只做一件事:为什么这样改、放弃了什么、怎么证明改对了,都留在一处,给下一个改这段代码的人用。

红线:先判要不要写,再谈怎么写

模型有迎合强迫症,动不动就想立 Note。先过这道闸:

快速返回——以下属于 DSH 定义的"纯机械或局部改动",严禁立 Note,直接改代码:

  • 纯排版格式化、错别字、无歧义重命名
  • 样式调整(不改行为)
  • 依赖补丁(不改行为)、版本发布打标(RC/Release tag)
  • 常规 CRUD、单模块内看 diff 即懂的显式逻辑修复(无跨文件影响)

判定对齐 DSH:非平凡改动必须写。 命中以下任何一项即非平凡——改了行为、改了架构、改了跨文件契约、改了流程与工具链、改了测试策略、改了落盘 / 网络 / 配置格式——或其他维护者日后可能重访的决定。

写之前,对照三个方向想清楚这篇笔记守住什么:

  1. 往前看(立新规)——新建的跨模块通信契约、状态流转规则、访问边界、运行时不变量。不记,后来的 Agent 各写一套、随意击穿模块。
  2. 往回看(记妥协)——为看不见的约束放弃了业界主流或直觉的解法。不记,被否掉的老路会被重走一遍。
  3. 做减法(收窄)——破坏性重构、代码裁剪、API 暴露面收窄。不记,没人知道退出条件和迁移边界,减法做不下去——或者做过了头。

一句话记住:代码和单测说不出来的意图、边界、取舍,就是非平凡。 判不准时,从严。

对 AI 来说,写在散文里的规矩等于没有规矩——能机械检查的纪律都有脚本兜底(见 §6);决定翻转、当场审计、现在时正文靠操作流,不靠词法扫描。 优先级:宿主项目的 AGENTS.md / CLAUDE.md 与用户的直接指令高于本 Skill;本 Skill 是默认契约,不是更高法律。
内心的借口现实
"只是改个默认值/重命名"默认值和命名都是决策事实;原地更新老笔记只要 30 秒
"先合并,以后再补"以后 = 永远不会;腐化从每一篇"以后补"开始
"代码即文档"代码只说是什么,说不出为什么放弃了什么
"改动很小,犯不着"规模小 ≠ 不用记;一个重试参数曾引发全网故障
"不确定要不要写"对照上面的非平凡清单:命中就写,不命中就不写。别拿这句话当挡箭牌
  • 优先就地同步,非必要不新建:在 DeepSeek 的公开演进历史里,Note 的变更大头是原地修改现有 Note 的事实(路径、类名、默认参数),而不是开新文件。已有归属的改动直接更新那篇!
  • 禁止把一篇 Note 改成另一个决定:事实(路径、符号、默认值)就地改;决定或理由翻转 → 新开一篇并互链。禁止把 ## Decision 改写成反面,禁止只靠 git 当旧理由的唯一副本。
  • 写新篇当场审计,不准推迟:按模块名/关键词搜 proposed + implemented + rejected;每篇命中当场分类:无关 / 部分重叠(互链)/ 完全吸收(删或归档)/ 过时提案(reject 或删)。分类结果和这篇新 Note 一起落盘。
  • 垃圾不进归档:过时提案转 Status: rejected — <原因>(严禁归档);无防坑价值的被否记录直接物理删除。
「决定」不重——个人项目里就是「为什么选 A 没选 B」。选型、取舍、踩过的坑,都值得写下。

0. 先探测,再落地

别一上来建全套目录。按这个仓库现在的样子选:

  1. AGENTS.md / CLAUDE.md / 贡献指南 → 读它;有 docs/adr/docs/decisions/、Issue 模板等现成的决定记录 → 沿用,状态和种类按本 Skill 的文件夹来即可。
  2. 没有现成的决定记录 → 按标准结构建:.agents/notes/{proposed,implemented,rejected,archived} × 6 class,用到哪个目录就建哪个,空目录不必预建——个人写、不用 git 也照此建全套结构,别精简成单目录。
  3. 团队长期仓库 → 在相同结构上叠加流程:CONTRIBUTING.md / PR 模板加一句「重要改动必带一篇笔记」,并把校验脚本接进 CI。

1. 路径即分类

每条 Note 的路径就是身份:{lifecycle}/{class}/yyyy-mm-dd-topic.md

Lifecycle(一层文件夹,这篇走到哪一步):

  • proposed — 想法阶段,有了方案但还没落地
  • implemented — 已落地,与代码同批改动保持同步
  • rejected — 审慎否掉的提案,仅当能防止重犯时保留,否则删整组
  • archived — 已完成且未来参考价值低的 implemented 记录,冻结不可改

Class(二层文件夹,就这 6 个;再加要改检查脚本):

  • feature 新能力 — 用户或模型看得见的选择(不显然的行为也算)
  • bug-fix 修缺陷 — 修好了什么,或补上复盘里暴露的缺口
  • simplification 只删不增 — 不增加能力,只删代码、行为或表面
  • architecture 结构怎么搭 — 发出去的源码怎么组织、包怎么连
  • process 工具和流程 — 检查、发布、怎么协作(围着代码转,不是运行时行为)
  • testing 测试怎么写 — 测试策略和基建
refactor 不单列:能看见的行为变了,归到对应类;没变就是 simplification。不建 INDEX.md。细判据见 references/classification.md

2. 文件格式(检查脚本会核对)

前三行固定:

markdown
# Agent Note: <标题>

Status: <状态>

状态必须与所在 lifecycle 文件夹一致(rejected 带一句话原因);文件名日期是首次提出日。Body 骨架:

  • proposed## Problem## Proposal → …自由节… → ## Alternatives considered## Acceptance criteria## Risks
  • implemented## Problem## Decision(现在时) → …自由节… → ## Alternatives considered## Consequences
  • rejected:冻结的 proposal 形态,结论在 Status:
备选方案必填:只记录真实考虑过的对手方案,先写它最强的理由再否定。没有过的选项不要编。「不做 / 复用现状」仅当当时真的权衡过才写。脚本只检查有没有 ## Alternatives consideredimplemented## Decision 用现在时;门禁只拒提案标题(## Proposal / ## Plan / ## Migration plan / ## Acceptance criteria 及其中文别名)。展开见 references/note-format.md

模板见 templates/

3. 动手前检索历史决策(去中心化 4 法)

动手重构或选型前,先查历史约束,防止重复踩坑或破坏前人妥协:

  1. 入口注释(若有):代码入口若已有 // Note: ... 见 .agents/notes/...,顺着它读。没有就走下面三法,不要为了检索去补锚点。
  2. 分类树物理切片:不扫全库,按意图直切目录(架构看 implemented/architecture/,避坑看 rejected/)。
  3. 精准全局检索:使用 ripgrep 搜关键词或机制名,必带 `--hidden` 并排除 `archived/`
bash
   rg --hidden --glob '!.agents/notes/archived/**' "<机制名或关键词>" .agents/notes/
  1. 模块文档下钻:子模块 README 涉及设计依据时,顺着相对 Markdown 链接直达对应 Note。

问用户之前,先自己查。 以上四法能答的事实,不要抛给用户;只有真正的决策才占用用户时间。

4. 什么时候写、什么时候改

对话里的触发信号——用户或自己说出这类话,就该动笔(文首红线清单里的机械改动除外,别拿这些短语当过度记录的理由):

  • 拍板新路线:"就选 X"、"决定用 X"、"我们先用 X 顶着" → 触发 Note
  • 比较中:"X 和 Y 怎么选"、"为什么倾向 X" → 触发备选记录
  • 同一段理由被解释了第二遍 → 该写下来了

判定与操作流:

  • 既有架构重构 / 路径迁移 / 参数改动【首选原地同步】:直接在持有该决定的老 Note 里修正事实(代码路径、方法签名、默认值),不另起新篇,也不要在正文追加流水账历史。## Decision 核心理由不变;理由变了就走新建。
  • 写新 Note 之前 → 按模块名/关键词搜活跃笔记,当场分类(见文首「当场审计」),禁止留到以后大扫除。
  • 新想法、还没动手 → 先写 proposed(为什么想这么做、考虑过哪几条路),评审完再动手。交互纪律见下。
  • 施工完(proposed → implemented),同一次改动里做完:① 移到 implemented/<class>/,文件名日期不动;② Status: proposedStatus: implemented;③ ## Proposal → 现在时 ## Decision;④ ## Acceptance criteria / ## Risks 折进 ## Consequences(或现在时 ## Testing);⑤ 删计划段。与代码同批落盘——git 场景即同一 commit/PR
  • 方案被新决策部分取代 → 两篇都留,双方加相对链接;只更新仍成立的事实。禁止归档。
  • 方案被新决策完全取代 → 新 Note 接管并写入旧篇全部独特理由/备选/后果/验证缺口;入站链接改完后,能删则删,不能删(旧篇仍有独立杠杆)再 archive-agent-note.ts。指针写在新笔记里,不写进归档篇。
  • 免写场景:见文首红线——快速返回清单里的,直接提交代码。

交互协议(向用户提问时):

  1. 先分 facts 和 decisions:环境里查得到的事实(代码、笔记树、rg)自己查完再问;只有真正要拍板的取舍才占用用户时间。
  2. 一轮全抛:所有待拍板的问题编号列出,每题独立一行给推荐答案 ➡️ <推荐>;用户按编号批量应答("1 yes,2 第二个选项"),不挤牙膏、不来回试探。
  3. 收敛靠确认门,不靠题数上限:落笔/动手前复述全部决定,用户确认达成共识后再执行——复述中被默认掉的任何一点,用户在确认时纠偏;没确认不动手。
  4. 开放决策超过五个是信号,不是配额:说明这次改动太大——拆成多篇笔记,或先交 proposed 草稿走评审,别在一次对话里硬塞。
判定细则见 references/when-to-write.md,归档与删除见 references/archiving.md

5. 怎么写好

  • ## Consequences 同时写代价和收益,不是只写"放弃了什么"。
  • 自由节(package 拓扑、wire 契约、schema 等)放在 DecisionAlternatives 之间,保持可检索的机制名与 must / may / never 时序强调。
  • 跨 Note 引用用相对 Markdown 链接 [topic](../../implemented/architecture/2026-…-….md),不要裸数字,以便机械可校验。
  • 宿主若已有此惯例,可在核心入口留一行 // Note: ... 见 .agents/notes/...;不是门禁。决定被取代时,这些注释是要同步的代码清单。
  • 文风与去推导痕迹见 references/prose-checklist.md;简化机会见 references/simplification-checklist.md
  • 写完后过一遍 references/quality-gate.md 的语义自检,只向用户报缺口和写得好的地方(≤5 行),缺口给具体修法。结构靠脚本,意思靠人点头。

6. 校验与运维命令

在仓库根目录直接运行(已配置 npm script 时):

sh
npm run verify-agent-note-tree     # 目录合法性、分类、文件名、笔记间相对链接
npm run verify-agent-note-format   # 头块、状态、必备节、备选方案、implemented 禁用提案标题
npm run verify-archived            # 归档封印:头部布局、manifest 哈希、只增不改(无 git 自动降级)
npm run verify-notes               # 以上三线串跑(CI 用这个)
npm run archive-agent-note <path> [--superseded-by <新笔记>]  # 一键归档;可选在新笔记插入互链 + 入站死链报告
npm run check-anchors              # 软报告:若代码里有 // Note: 锚点,做双向体检;不当 CI 门
npm run init-board                 # 生成 ~69KB 轻量看板 board.html(日常开发推荐)
npm run bundle-board               # 打包内嵌全量数据的自包含 demo.html

每个脚本都是独立 tsx(scripts/*.ts),也可 npx tsx scripts/xxx.ts 直接跑在任何目录;参数与免疫规则见 references/verification.md。看板要自定义输出路径时用 npx tsx scripts/build-board.ts --init <目标.html> "名字" / --bundle <notes目录> <输出.html> "名字"。团队可直接抄本仓库的 .github/workflows/verify-notes.yml,把 verify-notes 接进 CI;并在 CONTRIBUTING.md / PR 模板加一句「重要改动必带一篇笔记」。

References

按需加载:

  • references/note-format.md — 头块与 body 骨架展开
  • references/classification.md — 6 class 判定与边界
  • references/when-to-write.md — 何时新建 / 更新 / 流转(含与 DSH 判定对齐关系的说明)
  • references/archiving.md — 归档与合并删除(含"未来参考价值"判定)
  • references/prose-checklist.md — 行文与去泄露自检
  • references/simplification-checklist.md — 简化机会自检
  • references/quality-gate.md — 写后语义自检:Problem / Alternatives / Consequences / Verification 判定 + 汇报形态
  • references/verification.md — 校验脚本说明