Lesson 0020 · Productivity · 只能人启动(user-invoked)· 参考课

writing-great-skills:写 skill 的词汇与原则

你写了一个 skill,跑起来发现 agent 有时照步骤走、有时跳到一半就宣布完工; 你往正文里加了一句「要认真」,行为没有任何变化;你把它删了,行为还是没有变化。 这时候你需要的不是再试一次,而是一套能描述「skill 为什么这样表现」的词。 writing-great-skills 就是这套词的唯一权威出处: 它是一套关于「怎么把 skill 写好、改好」的词汇和原则,根美德叫 predictability(可预测性)——让 agent 每次运行走同一个过程。 它由两个文件组成:SKILL.md 是 83 行的原则正文, GLOSSARY.md 是 201 行的完整词条。 学完这节课,你拿到一个行为不对的 skill 时,能说出它得了六种失败模式里的哪一种、 该用哪根杠杆、去改哪个文件的哪一段。

1. 它在整个系统里站在哪

0001 把 22 个已发布 skill 分成三层:配置层(跑一次性的初始设置)、编排层(你手动启动的完整流程)、 纪律层(被反复调用的基本功)。writing-great-skills 不在这三层里干活—— ask-matt 的地图把它放在 Standalone(独立工具)一节,而且只有一句话: 「reference for writing and editing skills well」。 它是这套系统里唯一以 skill 本身为服务对象的 skill: 其它 21 个服务你的代码、issue tracker、学习过程;它服务 SKILL.md 的文本。 所以可以叫它 meta-skill(元 skill:关于 skill 的 skill)。

0001 的全表给它那一行写得极短,但四个格子都是考点:

格子 0001 里写的内容 翻译成人话
调用方式 U(user-invoked,只能人启动) 你打字 /writing-great-skills 它才来;agent 永远不会自己翻它
什么时候用 读或改某个 skill 时,需要「可预测性」词汇和失败模式清单 它是案头参考书,不是流程的一环
副作用 什么都不改(纯参考文档) 它不写任何文件;改动都落在你正在编辑的那个 skill 上
下一步 编辑具体 SKILL.md 时当检查单用 打开目标 skill 的文本,逐条对照本课的杠杆

这节课排在课程表的倒数第二(0020),位置是有意的:前 19 课教你这套系统, 这一课教你这套系统——MISSION.md 里说的「行为不对时定位该拧哪一段文本」, 拧之前需要的那套词汇,全在这里。

地图:0001 系统地图的 Standalone 一段 · 路由:ask-matt/SKILL.md 的 Standalone 一节 · 罗盘:MISSION.md

2. 它是什么、什么时候用

2.1 两个文件的分工

这个 skill 由两个文件组成。SKILL.md 是原则正文,83 行,开篇第一句就说: 加粗的术语完整定义在 GLOSSARY.md 里,要查全文去那边。 GLOSSARY.md 是 201 行的词条集,按四条轴分组,每个词条带定义和 Avoid(避免使用的近义词)列表。 这个分工本身就是它自己原则的一次演示——把不需要每次都读的内容压到链接文件里, 第 7 节的渐进披露会细讲。

SKILL.md 里有一句自我描述:「This skill is all reference.」 意思是它通篇是 reference(参考材料:按需查阅的定义、规则、事实), 没有 steps(步骤:要 agent 按顺序执行的动作)。 所以用它不是「跑一遍流程」,而是「对照着查」——查词汇、查原则、查失败模式, 然后回去改你手里那个 skill 的文本。

2.2 什么时候翻它,什么时候别翻

人读文档版列了四个典型时刻:决定一个新 skill 的调用方式、写 description、 决定什么住在 SKILL.md 什么住在链接文件、诊断一个行为走样的 skill。 展开成一张对照表:

情境 该翻 writing-great-skills 更该去哪
要写一个新 skill,先决定人、agent、别的 skill 谁能触发它 (第 4 节的 invocation 轴和两种 load)
description 写了一长串,agent 还是不触发、或者乱触发 (第 5 节的 description 三规矩)
skill 越写越长,不知道哪些内容该挪到链接文件里 (第 6、7、8 节的梯子、披露、拆分)
agent 总是做到一半就宣布完工,后面的步骤草草带过 (第 11 节的 premature completion)
想改项目的领域术语、维护 CONTEXT.md、写 ADR 不该(那是项目领域词,不是 skill 写作词) domain-modeling(0004)
不知道当前任务该走哪条 flow 不该 ask-matt(0019)
要给这个仓库加一个新 skill 并发布进插件 该,而且不够——还要走发布链 本课第 13 节 + 根目录 AGENTS.md 的发布纪律

权威原文: skills/productivity/writing-great-skills/SKILL.md · 词条全集: …/GLOSSARY.md · 给人看的叙事版: docs/productivity/writing-great-skills.mdaihero.dev/skills-writing-great-skills

3. 根美德:同一过程,不是同一输出

SKILL.md 的第一句话是这个 skill 的世界观: 「A skill exists to wrangle determinism out of a stochastic system.」 ——skill 存在的理由,是从一个随机(stochastic:每次采样都可能不同)的系统里拧出确定性。 拧出来的那个东西叫 predictability(可预测性): agent 每次运行走同一个过程,而不是产出同一个输出。 这两个字的差别是全部要点。GLOSSARY 给的例子是头脑风暴 skill: 它应该「可预测地」发散——每次写出的 token 都在变,但它的行为方式不变; 如果一个头脑风暴 skill 每次产出一样的东西,那才是坏了。

GLOSSARY 给 predictability 列了一串 Avoid(故意不用的近义词): consistency、reliability、robustness、output-determinism。 为什么避开?因为这些词都暗示「输出恒定」, 而 skill 能管的只有「过程恒定」——输出永远是采样出来的,过程才是文本能约束的。 这套词故意把话说窄,窄了才精确。

最后一句定位:全套词汇里的每一个术语都是 predictability 的一根杠杆; 成本(token 开销)和可维护性不是和它对立的竞争目标,而是它的症状—— skill 可预测了,这两样自然跟着变好。

读这套词汇的正确姿势 后面每学一个术语,都问一句:「它让每一次运行更可能走同一条路吗?走哪条路?」 答不上来,说明这个词你还没真正懂——回 GLOSSARY.md 读它的完整词条。

出处:SKILL.md 开篇 · GLOSSARY.md 的 Predictability 词条

4. 第一轴:调用方式、两种 load 和 router

GLOSSARY 里 Description 词条有一句话是整根轴的枢纽: 「它的存在本身就是 invocation 轴」—— 留着 description(frontmatter 里那个描述字段,skill 的机器可读触发器), skill 就是 model-invoked;把它从 agent 手里收走,skill 就是 user-invoked。 两种选择付两种不同的账:

Model-invoked(人和 AI 都能启动) User-invoked(只能人启动)
谁能触发 agent 自己判断触发;别的 skill 可以用一句「Run the /xxx skill」把它拉进来(0001 讲过的 prose 调用);人也仍然可以打字触发。没有「只有 model 能用」这种状态——description 只做加法,从不收走人的入口 只有人打字能触发。没有别的任何调用方:agent 看不见它,别的 skill 也够不到它(.agents/invocation.md 原话:nothing but the human can fire it)
每轮付什么账 Context load(上下文负载):description 每一轮都坐在上下文窗口里,同时花 token 和注意力——是 agent 侧的常驻成本 零 context load。改付 cognitive load(认知负载):就是索引,得自己记住这个 skill 存在、什么时候该用——是人脑侧的常驻成本
description 怎么写 面向模型写,带丰富触发语:「Use when the user wants…, mentions…, asks for…」 面向人写:一行摘要,触发列表全部剥掉(人是看着斜杠命令列表挑的,不靠触发语匹配)
机制(mechanics) 默认状态:不写 disable-model-invocationagents/openai.yaml 里也不放 policy 块 frontmatter 里设 disable-model-invocation: true,同时 agents/openai.yaml 里设 policy.allow_implicit_invocation: false——两套 harness 各藏各的,两份配置要保持同步

选择规则只有一条,原文照抄: 「只有当 agent 必须自己够到这个 skill、或者另一个 skill 必须够到它时,才选 model-invocation。 如果它永远只会被手动触发,就做成 user-invoked,一分 context load 都不要付。」 反过来也成立:user-invoked skill 多到人脑装不下时,堆起来的 cognitive load 由 router skill(路由 skill)来治——一个 user-invoked skill, 职责是点名其它 skill、各自什么时候用。 关键限制:router 只能 hint(提示),不能 fire(触发)—— user-invoked skill 没有 description,除了人谁也够不到它,router 自己也不例外。 活例就是 ask-matt:它对 writing-great-skills 的全部处理, 就是 Standalone 一节里那一行「点名 + 何时用」。

cognitive load 不是要消灭的成本 GLOSSARY 特意写明:cognitive load 不是要被最小化的东西,它是「human agency 的价钱」—— 人保留判断权就要付的记忆成本。花在「人的判断要紧」的地方(比如「现在该不该改这个 skill」), 省在「人的判断不要紧」的地方(比如「写测试要不要先确认接缝」这种纪律,交给 model-invoked 的 tdd 自动上场)。

本仓库有一份这一轴的「应用版」:.agents/invocation.md。 它把 GLOSSARY 的 Invocation 轴落成本仓库的具体约定:两套 harness 各自怎么把 user-invoked skill 从 model 手里藏起来、frontmatter 和 openai.yaml 要保持同步、 以及「user-invoked skill 可以调用 model-invoked skill,但永远够不到另一个 user-invoked skill」。 读完 GLOSSARY 再读它,会有一一对应的感觉。

出处:SKILL.md 的 Invocation 一节 · GLOSSARY.md 的 Model-Invoked / User-Invoked / Description / Context Load / Cognitive Load / Router Skill 词条 · 应用版:.agents/invocation.md

5. 写 description:一个分支一个触发

一个 model-invoked 的 description 干两份活:说清这个 skill 是什么, 再列出应该触发它的 branch(分支:这个 skill 被使用的不同情形, 不同运行会走不同路径)。description 的每个词都在涨 context load, 所以它比正文更值得狠删。SKILL.md 给了三条规矩:

  1. Front-load the leading word. 把领头词(leading word,第 9 节细讲:一个已活在模型预训练里的紧凑概念词)顶到最前面—— description 是领头词干 invocation 活的地方。
  2. One trigger per branch. 同义词给一个分支换着说法写两遍,就是 duplication(重复:同一个意思住了两个地方)。 原文给的例子:「build features using TDD … asks for test-first development」 是同一个分支写了两次。合并掉,只留真正不同的分支。
  3. Cut identity that's already in the body. 正文里已经讲过的「我是谁」别再搬进 description。 description 只留触发语,外加需要的「when another skill needs…」 reach 条款(写给别的 skill 看的可达性说明,告诉它们什么情况下可以把你拉进来)。

看一个本仓库的真实样本。to-tickets 的 description 开头是: 「Break a plan, spec, or the current conversation into a set of tracer-bullet tickets…」。 逐词拆:动作词 Break 顶在最前;紧跟三个真正不同的触发分支 (手里有一份 plan / 一份 spec / 只有一段对话); 领头词 tracer-bullet 直接长在第一个分句里; 没有一句话浪费在「我是一个很有用的 skill」这种自我介绍上。这就是三条规矩全及格的样子。

出处:SKILL.md 的 Writing the description 一节 · 样本:to-tickets/SKILL.md 的 frontmatter (它的流程课是 0010

6. 第二轴:信息层级的三级梯子

skill 由两种内容类型组成:steps(步骤)和 reference(参考材料), 两者自由混合——可以全 steps(tdd 就是)、全 reference(本 skill 就是)、或两者都有。 核心决策是每种内容坐在 information hierarchy (信息层级:按「agent 多快需要这份材料」排成的梯子)的哪一级:

SKILL.md 顶部(每次加载必读)
│
├─ 1. In-skill step        主层:有序动作。每步以 completion criterion 收尾
│
├─ 2. In-skill reference   按需查阅的定义/规则/事实;平铺是合法布局
│   (本 skill 全部住在这一级)
│
└─ 3. External reference   压出 SKILL.md,由 context pointer 指着,触发才加载
     ├─ disclosed:同目录 sibling 文件,仍是 skill 一部分(如 GLOSSARY.md)
     └─ external:skill 系统外的普通文件,任何 skill 都能指

第一级的关键是 completion criterion(完成判据: 告诉 agent 这一步算做完的条件)。它要满足两个性质: checkable(可检验:agent 能分辨「做完」和「没做完」), 要紧处还要 exhaustive(穷尽:写「every modified model accounted for」, 而不是「produce a change list」——前者逼 agent 全部核对,后者交个清单就能混过去)。 模糊的判据是在邀请 premature completion(提前收工,第 11 节的失败模式)。

第二级有个反直觉的许可:平铺的一组同侪条目(比如一次 review 的每条规则住同一级) 是合法布局,不是坏味道。本 skill 就是证据——83 行通篇平铺的原则, 一句 steps 都没有,原文明说「This skill is all reference」。

和梯子配套的一个词是 legwork(跑腿活:agent 在一步之内做的暗中挖掘—— 读文件、探代码、查材料,而不是把问题甩给用户)。它永远不是独立的一步, 而是被 demanding(要求高)的 completion criterion 逼出来的工作量。 而且这个驱动不挑 skill 有没有 steps: 「every rule applied」约束平铺的 reference,跟「every step done」约束一个序列,用的是同一根杠杆。 所以全 reference 的 skill 也能带穷尽性要求——比如一次 code review 要每条规则都过一遍。

整个决策的张力一句话:压得太少,顶部臃肿;压得太多,把 agent 真正需要的材料藏了起来。 这个张力就是全部——没有公式,只有判断。

本仓库的判据样板 diagnosing-bugs 的正文里有一节标题就叫 「Completion criterion — a tight loop that goes red」:第一阶段的完成判据是—— 能指名一条命令、已经真的跑过至少一次、 并且对这个 bug 会变红。可检验(跑了没有、红了没有,一看便知)、 要求高(不许「我觉得能复现」)。你写 skill 的 steps 时照这个标准磨判据。 (它的流程课是 0015。)

出处:SKILL.md 的 Information hierarchy 一节 · GLOSSARY.md 的 Steps / Reference / Completion Criterion / Legwork 词条 · 样板:diagnosing-bugs/SKILL.md

7. 渐进披露、branch 测试与 co-location

Progressive disclosure(渐进披露)就是沿梯子往下挪的那一刀: 把 reference 挪出 SKILL.md、挪进链接文件,让顶部保持可读。 机制很朴素:skill 目录里放一个按内容命名的 .md 文件—— 本 skill 把全部完整定义披露给 GLOSSARY.mdcodebase-design 把加深手法披露给 DEEPENING.md、 把并行设计披露给 DESIGN-IT-TWICE.md(0005 见过)。

什么时候该挪?branch 是最干净的披露测试: 每条 branch 都需要的内容,inline 留在正文;只有部分 branch 才会走到的内容,压到 pointer 后面。 一个全是平铺规则、所有分支都要全量过一遍的 review skill,反而没什么可披露的—— 这也解释了为什么平铺 reference 不是坏味道。

挪出去之后,材料靠 context pointer(上下文指针: 一段留在上下文里的文字,指着不在上下文里的材料,并编码了「什么时候去够它」的条件)够到。 最容易被忽略的一条原则:pointer 的措辞、而不是它指的目标,决定 agent 何时、 多可靠地够到材料。一份必须读到的材料躲在一个措辞软弱的 pointer 后面, 是一个 variance bug(稳定性 bug:同样的输入,有时读到有时读不到)—— 修法顺序是先磨 pointer 的措辞,磨了还是够不到,才把材料 inline 回来。 description 就是最顶层的那个 context pointer(上下文窗口 → skill), 所以第 5 节的三条规矩本质也是「磨 pointer 措辞」。

梯子管「压多深」,co-location(同置)管「压到那里之后旁边住谁」: 一个概念的定义、规则、注意事项收在同一个标题下,不要撒到文件各处—— 读到一处,它的邻居会跟着一起进上下文。 检验标准:skill 应该读起来像一份为 agent 写的文档;分组摆放的材料读起来像,撒开的读起来不像。 注意它和 duplication 的区别:duplication 是同一个意思重复在两处, scatter(撒开)是同一个意思碎在很多处——前者合并,后者收拢,治法不同。

co-location 的现场演示 打开 GLOSSARY.md 看一眼目录结构:词条按四条轴分组(Invocation / Information Hierarchy / Steering / Pruning),而且每个 failure mode(失败模式)就住在治好它的那根杠杆旁边—— 原文:「Each failure mode lives beside the lever that cures it」。 你读杠杆时顺手就看到了它防的是什么,读失败模式时顺手就拿到了药方。

出处:SKILL.md 的 Information hierarchy 后半 · GLOSSARY.md 的 Context Pointer / Progressive Disclosure / Co-location / External Reference 词条

8. 什么时候拆:两种切法

Granularity(粒度:skill 切多细)的每一刀都花两种 load 之一—— 拆出一个 model-invoked skill,付的是新 description 常驻窗口的 context load; 拆出一个 user-invoked skill,付的是人脑要多记一个名字的 cognitive load。 所以规则是「只在切得值的时候下刀」。SKILL.md 给了两种切法:

切法 什么时候下刀 付什么账 本仓库的活例
By invocation(按调用切) 有了一个独立的 leading word 该自己触发,或者另一个 skill 必须够到它——拆出一个 model-invoked skill 新 description 常驻每轮窗口的 context load,所以「独立可达」得值回票价 tdd 独立成 model-invoked:implement 要在内部拉它,人也想单独用它(0012
By sequence(按序列切) 一串 steps 里,后面的步骤(post-completion steps:排在当前步之后、还没做的步)在诱惑 agent 赶当前这一步——拆出去藏起来 一次真实上下文边界的跨越(新会话或 subagent);看不见后续,agent 才会在当前任务上做足 legwork 主 flow 要求每个 /implement 在干净上下文里开跑(0011),/handoff 就是那个边界(0006

GLOSSARY 补了一个反向警告:合并序列同样危险。 把两段 steps 并进一个 skill,等于把每一步的 post-completion steps 摆到它眼前, 正好招来 premature completion。拆和并是同一根杠杆的两个方向,都要过脑子: 拆,问「这一刀的 load 花得值不值」;并,问「暴露出来的后续会不会拽着 agent 赶工」。

出处:SKILL.md 的 When to split 一节 · GLOSSARY.md 的 Granularity 词条 · 上下文卫生的应用:ask-matt/SKILL.md 的 Context hygiene 一节

9. leading word:用预训练先验付账

Leading word(领头词,也叫 Leitwort)是一个 已经活在模型预训练里的紧凑概念,agent 跑 skill 时拿它思考—— 例子:lesson、fog of war、tracer bullets。 它在正文里作为 token 重复(不是作为句子被反复解释; 一个足够强的 leading word 甚至只需要出现一次), 每次出现都往同一个概念上累加,形成一种「分布式定义」, 用最少的 token 锚定一整片行为。它之所以便宜,是因为招募的是模型本来就有的先验 (priors:模型训练时已经内化了的联想)——你不花 token 解释,模型也大概知道 「tracer bullet」意味着什么。

自造词不是不行——定义写清楚就能用——但自造词招募不到先验, 预训练词免费给你的定义,你得自己掏 token 写。所以规则是:先找现成词

Leading word 双倍服务 predictability:

怎么猎捕?原文说:一个三元组在三个地方各自拼写了一遍(duplication)、 description 用一整句话比划一个想法——这些段落都在等着被 collapse(坍缩:把一段话压成单个 token)。原文给了两个例子:

坍缩前(一段话比划) 坍缩后(一个 token) 它在这套仓库里住在哪
「fast, deterministic, low-overhead」(一个性质在一整个阶段里被反复重述) tight(一个 tight loop) diagnosing-bugs:30 秒的 flaky 循环几乎不如没有,2 秒的确定性循环才是 tight——「a debugging superpower」(0015)
「a loop you believe in」(一个你信得过的循环,模糊的判断门槛) red(循环对这个 bug 变红,或者不变——模糊门槛变成二元可观察状态) diagnosing-bugs 的完成判据「a tight loop that goes red」(0015);tdd 的红绿循环也是同一个 red(0012

顺便把 GLOSSARY 点名过的几个词在这套仓库里的住处一起认了——你已经见过它们中的大多数:

Leading word 住在哪个 skill 它锚定的行为
tracer bullets to-tickets(0010) 每个 ticket 是一条端到端打穿的纵向切片,不是水平分层的一刀
fog of war wayfinder0016 地图故意不完整:看得见却还不能精确提问的区域留在雾里,frontier 推进时雾再毕业成 ticket
lesson / zone of proximal development teach(0021,下一课) 一节课教一件紧贴 mission 的小事,落在学习者的最近发展区里——你现在读的这个 HTML 就是这个词的产物

这不是巧合。Leading word 的 invocation 锚定作用要求同一个词住在 prompt、docs、代码里——这套仓库的 skill 共享一小批词,所以互相触发才可靠。 原文最后一句是个行动号召:假设每个 skill 都揣着能被 leading word 退休掉的复述——去找。双赢:token 更少,思维的钩子还更尖。

Leading word 和 no-op 的交叉口 一个太弱的 leading word 就是 no-op(空操作,第 10 节):「be thorough」对本来就挺 thorough 的 agent 没改任何默认行为。修法不是换技术(别再找新词种了), 是换一个更强的词——原文给的升级样本是 relentless。 所以 no-op 测试同时也是给 leading word 打分的方法:它的每次重复,挣到行为了吗?

出处:SKILL.md 的 Leading words 一节 · GLOSSARY.md 的 Leading Word 词条 · 住处验证:diagnosing-bugs · to-tickets · wayfinder · teach

10. 修剪:SSOT、relevance、no-op 测试

修剪(pruning)是保持 skill 苗条的日常纪律,三查按顺序过:

  1. Single source of truth(单一权威出处,SSOT): 每个意思住在一个权威地点,改行为 = 一处编辑。 你在两处写了同一个意思(duplication),将来改了一处忘另一处,行为就开始漂移。
  2. Relevance(相关性):逐行问「这行还和这个 skill 干的事有关吗」。 无关分两种:从来就无关(纯阐述,或者是一个该披露出去的 branch), 和过时了(skill 的行为或世界变了,这行没跟上)。 skill 越短越容易保持 relevant——每行的检查成本更低。
  3. No-op 测试逐句(不是逐行)孤立地问: 「这句话相对模型的默认行为,改变了什么?」 过不了的句子,整句删掉,而不是从句子里修词。 要狠——大多数过不了的散文是该删,不是该改写。

No-op(空操作)值得单独站直一点:它是一行模型默认就会照做的指令, 你付了 load 却什么都没买到。注意它和 relevance 的区别: relevance 问「和任务有关吗」,no-op 问「改了默认行为吗」—— 一行完全可以既相关、又是 no-op(比如在一个代码 review skill 里写「要读代码」: 相关,但 agent 默认就会读)。

还有一层容易争起来的:no-op 是 model-relative(相对于模型的默认行为), 不是 reader-relative(相对于读者觉得废不废话)。两个人争一句是不是 no-op, 争的其实是对「默认行为」的不同理解——GLOSSARY 给的裁决方式是: 跑一遍 skill 解决,别辩论

出处:SKILL.md 的 Pruning 一节 · GLOSSARY.md 的 Single Source of Truth / Relevance / No-Op 词条

11. 六个失败模式:症状 → 杠杆

SKILL.md 最后一节是失败模式清单,自我定位是 「用来诊断用户在 skill 上遇到的问题」。这就是你手里的诊断手册: 行为不对 → 对号入座 → 拿对应的杠杆。先上全表:

失败模式 症状(一句话) 杠杆 / 解法 容易误判成
Premature completion
提前收工
一步没真做完就收了,agent 的注意力滑向「做完」本身 先磨 completion criterion(便宜、局部);只有判据不可约地模糊、并且真观察到赶工,才按序列拆、藏起 post-completion steps 没 steps 的 skill 提前收工不是它——那是 thin legwork(判据的穷尽性没吃够)
Duplication
重复
同一个意思住了两个地方 合并到 single source of truth,一处编辑改行为 leading word 的 token 重复不算——那是有意重复 token,从不重复意思;它是 duplication 的有意反面
Sediment
沉积
旧内容一层层积着没人清——加感觉安全,删感觉危险 修剪纪律:relevance 逐行查,过时的清出去 长度本身(那是 sprawl);sediment 是「长度来自过时堆积」
Sprawl
蔓延
每行都活、都不重复,但就是太长 梯子:把 reference 披露到 pointer 后面;按 branch 或序列拆,让每条路径只扛自己要的材料 sediment(长度来自过时)和 duplication(长度来自重复)——sprawl 是长度本身,不问原因
No-op
空操作
写了模型默认就会做的事,付 load 白说 no-op 测试逐句过,过不了整句删;弱 leading word 换个更强的词 不相关的行——一行可以完全 relevant 但仍是 no-op;两个测试问的问题不同
Negation
否定式导向
靠「不要做 X」来导向,结果 X 被点名叫醒,更常出现 prompt the positive:直接描述目标行为,让被禁行为从未被说出口;无法正面表述的硬护栏才保留禁止,且必须配对「那该怎么做」

11.1 Premature completion 的力学

它是一个 between-steps failure(步与步之间的失败)—— 需要 steps 才发生;一个没 steps 的 skill 早早收工,不算 premature completion, 算判据的 demand(要求度)没吃够导致的 thin legwork。判别清楚了再下药。

它是一场拔河,两边各一股力: 拽着 agent 往前冲的是可见的 post-completion steps—— 后续步骤在上下文里露得越多,拉力越强; 抵抗的是 completion criterion 的清晰度—— 判据又硬又可检验,看见再多后续也扛得住。 所以模糊是必要条件:判据够硬的步,根本不需要防御。

防御顺序是固定的,别跳步: 先磨判据(cheap, local——改一句话的事); 只有判据「不可约地模糊」(这件事的完成标准本质上没法写得更硬), 并且你真的观察到了赶工,才动第二根杠杆: 按序列拆,把后续步骤藏起来。

「藏起来」只在真实上下文边界上有效 GLOSSARY 特意写明:藏后续步骤,必须跨过一个真实的上下文边界—— 一次 user-invoked 的交接(比如 /handoff 换个新会话,0006), 或者一次 subagent 派出(子代理拿到的是裁剪过的上下文)。 Inline 的 model-invoked 调用不算:被拉的 skill 内容进了同一个窗口, 后续步骤还在上下文里,什么都没清掉。 这正好解释了主 flow 的 context hygiene 为什么要求每个 /implement 在干净上下文里开跑(0011)——那不是洁癖,是 premature completion 的防御工事。

11.2 Negation 的力学

「Don't think of an elephant」(别想大象)——这句话一出口,大象就占满了脑子。 否定式导向适得其反的机制是:否定是个弱修饰词,会被强激活的概念碾过去。 你写「never write verbose comments」,agent 刚读到的模式是 verbose comments——禁令有一半会被读成指令。 GLOSSARY 甚至给这个被点名的东西起了个 leading word:elephant, 凡是禁令点名叫进画面里的,都是大象。

解法叫 prompt the positive(提示正面): 直接描述目标行为(「write one-line comments」),让被禁行为从未被说出口。 禁止只在一种情况下挣到位置:无法正面表述的硬护栏; 即便那时,也必须配对一句「那该怎么做」,让注意力落在目标上而不是禁令上。

自查:这套课程文件的写法就在躲 negation 回头看第 4 节表格的写法:「没有『只有 model 能用』这种状态——description 只做加法」。 它本可以写成「description 不会收走人的入口」(否定式),实际写的是 「只做加法,从不收走」(正面表述 + 顺带点破误区)。你改 skill 文本时, 把每个「不要 X」翻成「要 Y」,大象就消失了。

出处:SKILL.md 的 Failure modes 一节 · GLOSSARY.md 的 Premature Completion / Post-Completion Steps / Duplication / Sediment / Sprawl / No-Op / Negation 词条

12. 谁在用这套词,和它自己就是案例

12.1 严格答案:没有 skill 能依赖它

上一课类型的「谁引用它」表,对这个 skill 要换个问法。 它是 user-invoked:除了人,没有任何调用方够得到它—— 没有 skill 能在流程里把它拉进来(和 0005 的 codebase-design 完全相反, 那个是 model-invoked 的词汇地板,architecture、tdd、to-spec 都会 prose 调用它)。 它也不依赖任何别的 skill。依赖关系两端都是空的——这是设计,不是缺陷: 没有流程需要自动翻它,而人永远知道「我在写 skill」这个时刻。

但它的词汇确实住在几个地方,概念上的使用方是:

使用方 用了这套词的哪部分
.agents/invocation.md 第 4 节 invocation 轴在这个仓库的应用版:两种调用方式的机制、两套 harness 的同步、「user-invoked 够不到 user-invoked」
AGENTS.md 的发布纪律 README ↔ plugin.json ↔ docs 页 ↔ ask-matt 的同步链,本质是把「改一个 skill」做成 single source of truth 式的检查单(第 13 节展开)
ask-matt(0019) Router skill 的活例:一个 user-invoked skill 点名其它 user-invoked skill,只 hint 不 fire
domain-modeling 的纪律(0004) GLOSSARY.md 自称「The domain model for what makes a skill great」——词条 + 定义 + Avoid 列表的格式,正是 CONTEXT.md 的格式:把领域建模的纪律用在「skill 写作」这个领域上

12.2 它自己就是自己最好的案例

拿它自己的原则逐条自检,几乎全中——读它等于读一份「原则落地示范」:

  1. 全 reference,合法平铺:明写「This skill is all reference」。 梯子只用了下面两级(in-skill reference + disclosed reference),没有 steps—— 平铺不是坏味道,是它本来就有的样子。
  2. Progressive disclosure:完整定义披露给 GLOSSARY.md, 正文第一句就是 context pointer:「加粗术语的定义在 GLOSSARY.md」—— 你碰到 bold 词需要全文时,pointer 触发。
  3. Co-location:GLOSSARY 里每个失败模式住在治好它的杠杆旁边(第 7 节的 callout)。
  4. 调用方式自洽:没有 skill 需要自动拉它、agent 也不需要自己想起它 (人知道自己在写 skill)——按第 4 节的选择规则,做成 user-invoked,零 context load。
  5. description 人类向:一行摘要「Reference for writing and editing skills well — the vocabulary and principles that make a skill predictable」, 没有触发列表——正是 user-invoked 的 mechanics。
  6. 连「粒度」都自洽:它没有被并进某个「authoring 大 skill」, 也没有拆成六个小 skill——83 + 201 行,一个作者一次能读完的体量。
codebase-design(0005) writing-great-skills(本课)
调用方式 Model-invoked:别的 skill 要 prose 调用它 User-invoked:只有人翻它
词汇对象 模块的形状(module / interface / seam…) skill 的文本(description / steps / pointer…)
为什么是这种调用方式 architecture、tdd、to-spec 在流程中需要这套词——满足「另一个 skill 必须够到它」 没有任何流程需要自动拉它——人知道自己在写 skill
共同点 都是各自词汇的 single source of truth;都用 sibling 文件做 disclosed reference;都不写仓库里的任何文件

对照课:0005 codebase-design · 0004 domain-modeling · 路由活例:0019 ask-matt

13. 会留下什么、用完接什么、想微调改哪里

13.1 副作用:它自己什么都不写

0001 的全表写得明白:「什么都不改(纯参考文档)」。 它不写文件、不动 issue tracker、不碰任何 skill。 真正的副作用发生在你对照它动手的时候——编辑落在目标 skill 的文件上: SKILL.md 的正文、frontmatter 的 description、 sibling 披露文件、agents/openai.yaml。 记账时别把这笔账记到它头上。

13.2 在本仓库改完一个 skill 后的同步链

这是「推荐下一步」在本仓库的具体化。你在本仓库里新增、改名、改行为一个 skill 之后, 根目录 AGENTS.md 规定了一串必须跟着动的位置—— 这串清单本身就是 single source of truth 思想的应用(每样东西有一个权威出处,其余同步):

  1. .claude-plugin/plugin.jsonskills 数组——已发布集合的唯一权威出处;新增/删除 skill 必动。
  2. 顶层 README.md 和所在 bucket 的 README.md——promoted bucket(engineering / productivity)里的每个 skill 必须有条目,名字链到它的 SKILL.md,并按 User-invoked / Model-invoked 分组。
  3. docs/<bucket>/<skill>.md 文档页——promoted bucket 的 skill 有人读文档,行为变了要按 .agents/writing-docs.md 重新同步。
  4. ask-mattSKILL.md——user-reachable skill 新增、改名、删除或改了在 flow 里的位置时,必须重读并更新路由;「路由器说谎」是 AGENTS.md 点名的反模式。
  5. scripts/link-skills.sh——增删改名后重跑,保持本地软链最新。
  6. 碰过两个 manifest(plugin.json / marketplace.json)就跑 claude plugin validate . --strict

13.3 用完接什么

  1. 正在写新 skill → 按第 4 节定调用方式 → 第 5 节写 description → 第 6、7 节摆内容 → 发布走 13.2 的链。
  2. 正在改旧 skill → 0001 给的标准答案:「编辑具体 SKILL.md 时当检查单用」——第 10 节三查(SSOT / relevance / no-op)逐条过。
  3. 诊断出失败模式 → 按第 11 节的杠杆改目标 skill 的具体段落(13.4 的速查)。
  4. 不确定哪个 skill 该为某个行为负责 → 问 ask-matt(0019);它路由不了「改 skill」的问题,但能路由「干活」的问题。

13.4 行为不对时,去改哪个文件的哪一段

两个方向:这个 skill 本身不对劲,和拿它诊断别的 skill。

症状 先改哪里 不要误改
词条定义不准、要加新词、要改 Avoid 列表 writing-great-skills/GLOSSARY.md 对应词条——定义的 SSOT 在那边 SKILL.md 正文里同一词的压缩提法别另写一套(两处各写一份就是 duplication);让正文继续指向 GLOSSARY
原则的顺序、强调、例子不对 writing-great-skills/SKILL.md 对应那一节(Invocation / Information hierarchy / …) GLOSSARY 的词条定义(原则叙事和词条定义是两层)
想让它能被 agent 自动触发(或反过来) frontmatter 的 disable-model-invocation + agents/openai.yamlpolicy,两份同步改(机制见 .agents/invocation.md) 先想清楚——这等于重做它的 invocation 决策,不是拧文案
给人看的叙事版过时了 docs/productivity/writing-great-skills.md(按 .agents/writing-docs.md 同步) 记住 docs 不是行为真源——改它不改变任何 agent 行为
(别的 skill)该触发不触发、乱触发 那个 skill 的 description:触发语和 leading word(第 5 节) 它的正文步骤——触发问题在 pointer 措辞,不在正文
(别的 skill)步骤被赶工、提前收工 被赶那一步的 completion criterion(第 6、11 节) 别急着拆 skill——拆是第二根杠杆,先磨判据
(别的 skill)越写越长 第 7 节的披露测试和第 8 节的拆分规则;先分清是 sediment、duplication 还是 sprawl 别上来就删——三种长度病因不同,治法不同
(别的 skill)加了指令没效果 第 10 节的 no-op 测试,逐句过,过不了整句删 别再加更多同义指令去「加强」——那是 duplication
(别的 skill)越禁越犯 第 11.2 节:把「不要 X」改写成「要 Y」 别把禁令加粗加叹号——强调只会把大象喂得更壮

14. 检索练习

先别往回翻表,凭记忆答。选项的长度刻意对齐,不会从版式泄题。术语以本课和 SKILL.md / GLOSSARY.md 的精确定义为准。

自测(立即反馈)

1. Predictability 要求每次运行保持相同的是什么?
2. 一个 user-invoked skill 为「零 context load」付的代价是?
3. 按原文规则,什么时候才该把一个 skill 做成 model-invoked?
4. description 里写「build features using TDD … asks for test-first development」犯了什么错?
5. 信息层级的三级梯子,从上到下正确的顺序是?
6. 观察到 agent 赶工提前收步(premature completion),第一手防御是?
7. 「把 post-completion steps 藏起来」在什么边界上才真的有效?
8. 为什么 negation(靠禁止来导向)会适得其反?
额外提取练习(无选项) 合上本页,做三件事: 一、默写六个失败模式,各配一句「杠杆是什么」(premature completion、duplication、sediment、sprawl、no-op、negation——sprawl 最常被漏掉); 二、写出两种 load 的名字和各自的「付账人」(context load 谁付?cognitive load 谁付?); 三、从你最近写给 agent 的一段 prompt 或 skill 文本里,找一个 no-op(相对默认行为没改任何东西的句子) 和一个可以 collapse 成 leading word 的三元组复述。写完对照第 10、11 节。

15. 下一课与一手材料

本课主一手材料(请打开原文读,不要只背本页摘要——83 + 201 行,一次能读完):

速查页(本课同步): reference/writing-great-skills.html

导航: 上一课 0019 ask-matt (router 概念的肉身——第 4 节的 router skill 就是它)。 总览仍回 0001 系统地图; 平行的词汇地板课见 00040005

建议下一课(0021,并行编写中): teach——这套课程的生产者, 也是 leading word 的活案例库(lesson、zone of proximal development 都是它的词)。 和本课的交接点:读 teach/SKILL.md 时顺手做第 9 节的猎捕练习—— 数数它用了几个 leading word、哪些句子其实通不过 no-op 测试; 用刚学的词汇读一个真实 skill,比再做十道选择题更固化。

老师就在会话里。 对本课任何一个术语的边界有疑问——比如 disclosed 和 external reference 的分界、 「不可约的模糊」到底怎么判断、一个具体的句子算不算 no-op——直接在对话里问。 回答会回到 SKILL.md / GLOSSARY.md 的原文,不会临场编造。 做完检索练习后,回复「练习结果 / 哪里卡住 / 开 0021 或先补 0019」,我们安排下一课。