grill-with-docs 精读:同一个访谈,为什么它敢往你的仓库里写文件
grill-with-docs 的正文只有一句『调用 grilling 和 domain-modeling』。本文讲清楚它和 grill-me 的唯一差别是有工作目录,走一遍术语、ADR、对话三条产出的不同门槛,用 git diff 还原 88 行被删掉的过程,并说明薄指针的代价——依赖没加载时它会静默失灵。
(本文读的是 mattpocock/skills 快照 5beb35b,2026-10-19,引用原文都能按文中路径回仓库核对。这是「逐个技能精读」系列的第三篇,聚焦 grill-with-docs。)
七行,正文只有一句
skills/engineering/grill-with-docs/SKILL.md 全文:
---
name: grill-with-docs
description: A relentless interview to sharpen a plan or design, which also creates docs (ADR's and glossary) as we go.
disable-model-invocation: true
---
Call the Skill tool twice, for "grilling" and "domain-modeling".
注意那个 twice。仓库 .agents/invocation.md 专门解释了这句语法:Skill 工具一次只接受一个技能,需要两个就是两次调用;写成「call it with X and Y」会被读成一次带两个名字的调用,行为就变了。这句一行的正文里,每个词都在承重。
走一遍真实路径。你已经在某个 repo 里,敲 /grill-with-docs;agent 先加载 grilling 拿到访谈,再加载 domain-modeling 拿到落盘纪律;于是整个过程变成「聊 + 写」并行——每聊定一个术语就往 GLOSSARY.md 里写一条,每定下一个跨不过去的决定就往 docs/adr/ 里放一条。
它和 grill-me 的唯一差别:stateful
同一个访谈、同一套 design tree / frontier / 一轮问完 / 每题带推荐答案。差别只有一处:你有一个工作目录。文档的表述是“Every other grilling skill leaves the session in your head; this one leaves files on disk.”
有了这个目录,它就从「一次性谈话」变成主流程的起点。ask-matt 里主流程的第一格就是它:
grill-with-docs → to-spec → to-tickets → implement → code-review → retro
怎么在这三个访谈技能里选,文档给了一张表:没有工作目录 → grill-me;一个会话能聊完的改动 + repo → grill-with-docs;一个大到一个会话装不下的工程 → wayfinder。分界线就是会话数,不是话题类型。
三类产出,门槛完全不同
一次会话会蹦出很多东西,但只有两类有资格落盘,而且门槛不一样:
| 聊出来什么 | 落在哪 |
|---|---|
| 一个术语(项目自己的词) | GLOSSARY.md,随解随写,不批量 |
| 满足三门槛的决定 | docs/adr/ 里的一条 ADR |
| 其余全部 | 只在对话里,别处没有 |
第三行是最容易让人误判的。文档原话:“The glossary is not a spec, most answers do not earn an ADR, and no record links each resolved answer to a spec, a ticket and a test.” 换句话说,大多数你亲口定下的答案,会话结束后就只活在上下文里。所以文档反复强调:别 clear,直接把这段对话交给 /to-spec。
它有意识摒弃了什么
一、摒弃了把 domain 规则抄进自己正文。 证据在 git 里最硬。221ffca(2026-05-31)那次提交,skills/engineering/grill-with-docs/SKILL.md 的 stat 是 88 +---------------——88 行里删掉了绝大部分。被删掉的是原来内联的完整 domain 纪律:「挑战术语」「锐化模糊语言」「用具体场景压测」「和代码交叉印证」「随解随写」「三条门槛」。这些内容一条不少地搬进了新建的 domain-modeling。今天留在原地的只有一句委派。
这正好和 writing-for-agents 里的一条原则对上:单一来源。同一段规则被两个技能各存一份,改的时候就要改两处,迟早分叉;而分叉之后,模型看到哪份就按哪份走。
二、摒弃了批量写盘。 术语随解随写。文档把它列为「它在工作中」的第一条判据:“GLOSSARY.md changes during the session, term by term, rather than appearing in one lump at the end.” 批量的坏处是:中途上下文一断,整批都没了;而且批量会让模型把「一共聊了哪些词」当成一次总结任务,而不是把每个词当场钉死。
三、摒弃了滥发 ADR。 domain-modeling 给了三条门槛,必须同时满足才写:难逆(“the cost of changing your mind later is meaningful”)、脱离上下文会奇怪(“a future reader will wonder why did they do it this way”)、是真取舍(“there were genuine alternatives and you picked one for specific reasons”)。缺一条就跳过。文档的观察很直白:“most decisions do not qualify and most sessions produce none.” 一个只让词表变干净、零 ADR 的会话,是按设计工作的。
四、摒弃了预置脚手架。 它不要求你先建好目录结构。原文:“Create files lazily: only when you have something to write.” 没有 GLOSSARY.md 就等第一条术语定下来时再建,没有 docs/adr/ 就等第一个够格的决定出现时再建。空目录不会有,空文件也不会。
五、摒弃了让 GLOSSARY.md 变成杂物间的可能。 同一句被写了两遍、语气很重:“totally devoid of implementation details… It is a glossary and nothing else.” 不是 spec、不是草稿本、不是实现决定的仓库。
六、代价:它牺牲了自己的健壮性。 这是这一篇最该被记住的部分。因为正文只有一句委派,一旦两个依赖里有一个没加载上,agent 就会自己瞎猜「grilling 是什么意思」。文档描述的症状很具体:所有问题一次问完、没有推荐答案、全程不提 GLOSSARY.md;更糟的是只加载一半——访谈正常、纸面记录消失。文档承认这是这个技能被报告最多的问题,而且“the bug is filed and unfixed”。
薄指针不是免费的。它的代价是:任何一环没接上,你看到的不是报错,而是一次看起来正常、实际残缺的会话。所以文档给了用户一个排查动作——直接问 agent 它加载了哪些技能。
原文证据
skills/engineering/grill-with-docs/SKILL.md 全文即上文七行。
skills/engineering/domain-modeling/SKILL.md 里的 ADR 三门槛(快照 5beb35b):
Only offer to create an ADR when all three are true: 1. Hard to reverse 2. Surprising without context 3. The result of a real trade-off
以及它对自身边界的一句自我限制:
(Merely reading
GLOSSARY.mdfor vocabulary is not this skill: that’s a one-line habit any skill can do. This skill is for when you’re changing the model, not just consuming it.)
这句区分很重要:读词表是任何技能都会顺手做的小习惯,不配叫技能;改词表才是 domain-modeling。边界划在「消费」和「生产」之间,不是划在「用到没用」。
可迁移结论
- 组合式技能写成「调两次」。 需要两个技能就说两次调用,别让一行字承担两种读法。这个细节决定了下游是并行跑两件事,还是当成一件事做砸。
- 明确规定什么够格落盘。 「聊出来都写下」会让文档迅速腐烂;给出可判定的门槛(三条同时满足),绝大多数东西自然被挡在外面,而挡在外面是正确结果,不是失败。
- 懒创建。 不要为了让结构看起来完整而生成空文件;文件在第一次有内容时出现,仓库里就不会有「占位但不含信息」的垃圾。
- 状态要落在已经被其他技能认识的地方。 术语放
GLOSSARY.md、决定放docs/adr/,是因为整套技能都按这个名字去找。换名字要连带改一圈,所以文档专门提醒过这件事。 - 薄指针要配一份「没加载上会怎样」的诊断。 这是最实用的一条:把失败症状写出来(全部一次问完、没有推荐答案、不提
GLOSSARY.md),你才有机会在残缺会话里发现异常。
把 grill-me 和 grill-with-docs 并排看,会发现两者正文几乎一样薄,差别只在「有没有一个目录可以写」。真正撑起后者的不是它自己的正文,而是它调用的那两个技能,以及一份说清楚「什么才算值得写下」的门槛。
讨论
用 GitHub 账号留言;评论保存在公开仓库chengshu-blog-discussions的 Discussions 里。也可通过 RSS 订阅后续文章。