管两端,放中间:DeepSeek 用 64 天 12,293 个 commits 教会我们的 AI 写代码哲学——dsh 方法论拆解
posts posts 2026-08-17T01:30:00+08:00拆解 CY-Christin 对 deepseek-harness(dsh)仓库的方法论反写:64 天、12,293 commits、几乎全由 AI 写成的代码库,背后是一套「管两端,放中间」的工程哲学——事实做成工具、验收交给机器、思考还给 AI。技术笔记AI Agent, DeepSeek, 开发方法论, 工程哲学, Code Review管两端,放中间:DeepSeek 用 64 天 12,293 个 commits 教会我们的 AI 写代码哲学
先给你看一组数字。
一个仓库,64 天,12,293 个 commits。平均每天接近 200 次提交。陪同它长大的,是 .agents/notes/ 目录下 700 多篇决策文档、docs/postmortem/ 里 4 篇事故复盘(postmortem),以及 .agents/skills/ 里 11 个各自 900 到 2000 词的 skill 文件。这个仓库叫 deepseek-harness,内部简称 dsh,出自 DeepSeek 团队。
而它的代码,几乎全部是 AI 写的。
在「AI 辅助编程」这个话题已经被讲烂的今天,绝大多数讨论停留在 prompt 技巧、IDE 插件、补全速度这些皮毛上。dsh 不一样的地方在于:它是一个足够大、足够快、足够真实的样本——大到能暴露 AI 写代码的所有结构性问题,快到任何事后归因都来不及粉饰,真实到每一道门禁背后都能翻出一条具体的血泪史。市面上讲"我用 AI 写了项目"的文章很多,能拿出 12,293 个 commits 加 700 篇决策文档让你逐条对账的,据我所知只有这一个。
CY-Christin 把这个仓库从里到外拆了一遍,写成了 learn-ai-dev-from-deepseek 这个项目(GitHub 地址)。八章文档,从背景数据到一手拆机,回答的核心问题只有一个:
当写代码的人不再是人,工程管理该管什么?
顺便交代一下这个拆解项目本身的结构,方便你按图索骥:第一章背景数据交代 dsh 这个仓库的体量与开发节奏;第二章讲 .agents/notes/ 里那 700 多篇 Agent Notes(决策文档)怎么写、怎么归档;第三章拆机器门禁的三层防线;第四章逐个讲 11 个 skill 的诞生过程;第五章讲输入端的事实供给机制;第六章讲测试哲学;第七章是一份诚实的「可借鉴 / 不可照搬」清单;第八章是作者的一手拆机记录,把前面所有论断对应回 dsh 仓库里的真实文件。八章读下来,论断和证据始终能对上号——这在方法论类文章里是稀缺品质。
dsh 团队给出的答案,用他们自己的话说,五个字:管两端,放中间。
一、管两端,放中间:一句被低估的工程纲领
这句话值得逐字拆开。
输入端,管的是事实。 AI 最大的问题不是不聪明,是会把想象当成记忆。你跟它说"这个函数在 src/utils.ts 里",它会顺着你的话往下编。dsh 的做法是:凡是 AI 需要知道的事实,全部做成工具,让它自己去查,而不是写在 prompt 里叮嘱它记住。决策依据写在 .agents/notes/ 的 700 多篇笔记里,每次改动的影响面由 change-scope 工具现场算出来,4 篇 postmortem 里记着每一次翻车的完整现场。AI 不需要"记得"这个仓库的历史,它只需要会查。
这里有一个容易滑过去的区分值得强调:事实供给(facts)和指令叮嘱(instructions)是两回事。“修改配置后记得同步文档站"是指令,写进 prompt 十次,AI 总有忘掉的那一次;而"文档站同没同步,CI 里的 verify-* 脚本一查便知"是事实,AI 跑到那一步自然会被拦下来。dsh 把能做成事实的东西全部从 prompt 里搬出来,落进文件系统、工具和脚本里。prompt 因此得以保持短小——根目录那份给 AI 看的 AGENTS.md 只有 149 行,在同类项目里短得出奇。约束越少,剩下那 149 行里每一条的分量反而越重。
输出端,管的是验收。 AI 交上来的东西,不看它怎么说的,只看它做成什么样。机器能验的全部交给机器——CI(持续集成)卡住一切硬性指标;机器验不了的语义问题,交给一份写得极细的 review 手册。AI 的自述在这个系统里一文不值,只有重新读一遍文件、重新跑一遍命令、外部复查一遍结果,才算数。
中间,什么都不管。 AI 怎么思考、分几步走、先写测试还是先写实现,一概不约束。这一点最反直觉,也最见功力。绝大多数团队管 AI 的方式是反过来:给一堆 prompt 模板框住它的思路,验收却稀里糊涂——结果思路被框死了,产出照样没法信。dsh 把自由度全部留在中间,把严格度全部堆在两端。因为他们想明白了一件事:你不可能用几句话管住一个比你能写的东西的脑子,但你可以管住它能看到的事实和它必须通过的闸门。
第六章的测试哲学可以为这种「放任」兜底:测试在这个体系里不是质量保证手段,而是事实供给的一部分——它向 AI 声明「这个世界现在长什么样」。所以他们对凑数测试的警惕才那么高:一份没有断言的测试不是质量漏洞,是喂给 AI 的假情报,污染的是输入端。
二、蒸馏,不是预先规定:规范是实践的沉淀物
看 dsh 的 11 个 skill,最震撼的不是内容,是它们的生日。
根据 docs/04-skills蒸馏.md 的记载,这份清单按时间排开是这样的:
- 06-13
dsh-code-review——怎么 review 本仓库的 PR - 06-20
dsh-find-simplifications——找简化机会 - 07-02
dsh-translate-docs——中英双语文档 - 07-04
dsh-doc-standards——文档分层与预算审计 - 07-06
dsh-pre-push-checks——push 前检查 - 07-06
dsh-merging-stacked-prs——合并堆叠 PR - 07-13
dsh-doc-site-sync——文档站同步 - 07-13
dsh-prose-standard——技术散文写作标准 - 07-23
record-browser-gif——录浏览器演示 GIF - 07-26
dsh-archive-agent-notes——决策文档归档判断 - 08-09
dsh-trim-cot-leakage——清理 CoT 泄漏
注意看这个时间轴。项目开工后第 13 天才有第一个 skill,而且它是 code review——显然是先被 AI 交的烂 PR 恶心到了,才回头写规范。后面每出现一个 skill,你都能猜到前面发生过什么:先有文档乱到读不下去,才有文档标准;先有 push 上去 CI 挂掉的社死现场,才有 pre-push 检查。
没有一个 skill 是预先设计的。 这就是标题里那个对比——蒸馏(distill)vs 预先规定(prescribe)。预先规定是开工前抄一份《阿里巴巴Java开发手册》贴在墙上,里面的条款和你的项目没有任何血缘关系;蒸馏是每出一次事故,就把事故里提炼出来的规则固化下来,让它变成下一道闸门。前者的规则是借来的,后者的规则是自己挣的。
这个区别决定了规则的生命力。借来的规则没人维护,三个月就变成摆设;挣来的规则背后站着一篇 postmortem,谁想动它,先得翻过那段血泪史。
三、机器门禁三层:机器管事实,review 管语义
dsh 的验收体系分三层,每一层的定位清楚得像刀切(详见 docs/03-机器门禁.md):
第一层是 git hooks,用 lefthook 管。 pre-commit 跑快速 lint,pre-push 跑增量类型检查。原则是本地不卡手——快的东西放本地,慢的东西往后推。
第二层是 CI,狠的全在这里。 严格 TypeScript(noUncheckedIndexedAccess 之类的开关全开)、每个文件 100% 测试覆盖率、jscpd 查重复代码、knip 查死代码、3 个 Node 版本的测试矩阵、每个入口的冒烟测试。这套配置放在人类团队里会被骂变态,但 AI 不会抱怨。
第三层最有特色:自写的 scripts/verify-* 脚本群。 举几个例子:
verify-doc-budgets——文档超过字数预算就挂。是的,他们给文档定了字数,写在 manifest 里,超一个字 CI 就红。verify-agent-note-format——决策文档的格式检查。最狠的一条:已经 implemented 的 note 里出现 “should” 这个词直接挂掉。都实现了你还在那里"应该”?verify-md-links——Markdown 里的死链、死锚点全查出来。verify-translation-pairing——中英文档结构必须同步,中文版多一节英文版少一节,挂。verify-export-jsdoc——公开导出的函数缺 JSDoc 注释,挂。
这三层背后是一句分工纲领:机器管事实,review 管语义。能用 exit code 非零表达的检查,全部写进 CI,一条不留;机械检查表达不了的(比如这个设计是否合理),写进 review 手册由人来判;既机械不了又没人愿意 review 的,直接删掉——因为它已经是摆设,留着只是自欺欺人。
还有一条配套原则,可能是整个体系里最成熟的一条:每上一道闸门,记录它诱导出的坏行为。 100% 覆盖率门禁上线当天,他们就提案引入 mutation testing(变异测试——故意往代码里塞 bug,看你的测试能不能抓住)来对冲。为什么?因为他们预判到 AI 会为了凑覆盖率写一堆没有断言的凑数测试。闸门上墙的同时,监控闸门副作用的探头也装上了。这种"我知道我的规则会被钻空子,所以我提前盯着钻空子的方式"的自觉,在人类工程管理里都不多见。
四、最有戏的一段:skill 半自动修订流水线
如果整个项目只能挑一段细讲,我选这个。
既然 skill 是 AI 行为的操作手册,那 skill 本身的修改就是最高危的操作——改错一句,AI 全仓库的行为跟着跑偏。dsh 为 skill 修订设计了一条流水线,其 paranoid 程度堪比金融机构的上线流程:
双 AI reviewer,且互相不信任。 两个 reviewer 来自不同的 provider、不同的模型。更绝的是,工具会拒绝运行两个字节完全相同的可执行文件——也就是说你不能拿同一个模型的两份拷贝糊弄,它们必须在二进制层面就是不同的东西。这个细节我第一次读到时愣了几秒:他们连"reviewer 之间发生同源污染"这种场景都防了。
git 三方比对。 修改不是 diff 一下完事,而是拿 base、修改前、修改后三方对照,确认每一处改动都有出处。
128 位随机 nonce 防 prompt 注入。 skill 文件的内容是要喂给 AI 的,万一里面被人埋了一句"忽略你之前的指令"呢?流水线生成 128 位随机数作为边界标记,AI 只认标记内的内容,注入的指令进不了有效区域。
子进程环境变量全洗。 跑修订工具的子进程,环境变量全部清洗一遍,防止通过 PATH、LD_PRELOAD 之类的渠道夹带私货。
人工 PR review 兜底,工具永远不自动 merge。 所有自动化走到最后一步停下来,等人类点 merge。自动化的尽头是人。
然后是最让我佩服的一点:失败也如实记录。
文档里记载了一次流水线的完整运行:62 个 PR,426 条人类反馈,跑完之后的产出是——0 个候选。一个都没通过。换成别的团队,这种"白跑一趟"的记录大概率不会出现在正式文档里。他们不仅写了,还写了细节:adapter 层产生了幻觉 ID,被 fail-closed 机制兜住——也就是宁可全部拒掉也不放过一个可疑的。
还有一层清醒:这套流水线投入不小,他们自己评估下来收益没过成本线,于是明着豁免——工具不入仓。连豁免理由和将来什么条件下恢复都留了案。这就是他们的"成本收益豁免"原则:每条重规则都要过"收益大于维护成本"这一关,过不了就坦白豁免,不打肿脸充胖子。
五、dsh-trim-cot-leakage:对 AI 写作病最精准的一次解剖
11 个 skill 里最后一个诞生的(08-09),dsh-trim-cot-leakage,处理的是 CoT leakage(思维链泄漏——AI 把自己的思考过程当成正文写进文档的毛病)。
它对 AI 写作的病灶分类,精准到让我这个读过太多 AI 生成文档的人想鼓掌:
- 叙述历史——“我首先检查了 X,然后修改了 Y,最后运行了 Z”。没人关心你的心路历程,文档里留下结果就行。
- 状态标注——“注意:此功能目前是实验性的(截至本次提交)"。这种话提交信息里写,别写进正文。
- 推理过程复述——把选择这个方案的理由洋洋洒洒写三段,正文只需要结论和最关键的取舍。
- 强调通胀——“非常重要!““极其关键!“每段都加粗等于没有加粗。
- 跟不存在的 reviewer 辩论——“有人可能会问为什么不选 B 方案……“文档里没人问你,有异议走决策文档。
最狠的是它给出的兜底判定标准,只有一句话:只有当前代码的读者,能否解析文中的每一个引用? 文中提到的任何文件、任何讨论、任何上下文,如果读者需要翻看 git log 或当时的聊天记录才能懂,那就是泄漏,删掉。一条标准,判尽天下 slop。
顺便说,他们管这类 AI 文档通病叫 slop(泔水),还维护了一份 slop 清单作为审查清单。命名即态度。
六、零成本可抄的三条
看完整套方法论,docs/07-可借鉴清单.md 里标出了三条不需要任何基础设施、今天就能用的:
第一,验证世界,不验证自述。 AI 说"我改好了,测试全过”——别信。让它重新读一遍改后的文件,重新跑一遍命令,最好你再从外部复查一次。验收的对象永远是世界的状态,不是 AI 关于世界状态的陈述。这一条不需要写任何代码,只需要改一个习惯。
第二,决策留档,替代方案必填。 每个重要决策写进决策文档,而且被否决的方案也必须写清楚为什么被否决。否决记录比通过记录更值钱——三个月后 AI(或新来的人)想重提旧案,看到否决理由,就能直接死心,不用把坑再踩一遍。
第三,用 slop 清单审 AI 写的文档。 把上面那五类病灶做成 checklist,每篇 AI 产出的文档过一遍。成本是每次几分钟,收益是文档库半年后还读得下去。
七、不该照搬的,和这套东西的边界
诚实是这份拆解最可贵的品质之一,作者明确列出了四条"不建议照搬”:
- 每文件 100% 覆盖率门禁——它能成立的前提是 AI 劳动力免费。人类团队照搬这个,测试维护成本会吃掉开发速度。
- 中英双语文档三件套加配对门禁——除非你真的有双语受众,否则这是双倍维护成本换零收益。
- 字数预算 manifest 加全套 verify- 脚本*——单人小项目手动执行就行,写成 CI 是杀鸡用牛刀。
- skill 半自动修订流水线——他们自己跑到最后也只停在 proposed 阶段,0 候选。投入产出比摆在那里。
适用边界同样说得坦白:这套方法论成立,需要参与者全受控——dsh 不收外部 PR,所有贡献者遵守同一套规则,开源项目做不到这一点;需要推理成本不敏感——“我们是 DeepSeek,别省真实 API 测试"是文档里的原话,不是每个团队都有这个底气;需要规模匹配——日均 200 个 commits 的强度,才让防合并冲突这类机制的回本周期变得合理。你的项目一周三个 commit,照抄这套就是行为艺术。
结语
这套方法论对技术决策者的真正启示,或许不在任何一条具体规则里,而在规则的形成机制上。dsh 团队做的事,本质上是把"组织学习"这件事压缩到了天级粒度:白天 AI 把坑踩出来,晚上坑就变成 postmortem 和门禁脚本,第二天同类错误在物理层面就不可能再犯。传统团队的学习循环以季度计,他们以天计——这才是 64 天 12,293 个 commits 背后真正难以复制的东西,不是 AI 写得快,是这个组织迭代自己的规则迭代得快。
读完这个项目,我一直在想一个问题:为什么偏偏是 DeepSeek 写出了这套方法论?
答案可能很简单:因为他们是最早真正把 AI 当主力劳动者用的团队之一,也是最早被 AI 的种种毛病按在地上摩擦的团队之一。12,293 个 commits 里藏着人类团队几年才能踩完的坑,他们把每个坑都变成了 .agents/notes/ 里的一篇笔记、scripts/verify-* 里的一个脚本、或者 .agents/skills/ 里的一个 skill。连根目录那份 149 行的 AGENTS.md,都是浓缩再浓缩之后剩下的骨架。
「管两端,放中间」表面上是管理 AI 的策略,往深里说是一种对人(和对非人)都很老练的工程态度:不给对方灌输你认为正确的思考方式,只保证对方站在真实的地面上、穿过诚实的闸门。至于中间那段路怎么走——那是它自己的事。
想亲手翻翻这个仓库的话:
git clone https://github.com/CY-Christin/learn-ai-dev-from-deepseek.git
cd learn-ai-dev-from-deepseek
wc -l docs/*.md八章文档不长,但每一页背后,都是 64 天和 12,293 次提交压出来的分量。
参与讨论
使用 GitHub 登录。欢迎补充事实、异议与实践。
讨论暂时无法加载。