你写了一个 skill,跑起来发现 agent 有时照步骤走、有时跳到一半就宣布完工;
你往正文里加了一句「要认真」,行为没有任何变化;你把它删了,行为还是没有变化。
这时候你需要的不是再试一次,而是一套能描述「skill 为什么这样表现」的词。
writing-great-skills 就是这套词的唯一权威出处:
它是一套关于「怎么把 skill 写好、改好」的词汇和原则,根美德叫
predictability(可预测性)——让 agent 每次运行走同一个过程。
它由两个文件组成:SKILL.md 是 83 行的原则正文,
GLOSSARY.md 是 201 行的完整词条。
学完这节课,你拿到一个行为不对的 skill 时,能说出它得了六种失败模式里的哪一种、
该用哪根杠杆、去改哪个文件的哪一段。
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
这个 skill 由两个文件组成。SKILL.md 是原则正文,83 行,开篇第一句就说:
加粗的术语完整定义在 GLOSSARY.md 里,要查全文去那边。
GLOSSARY.md 是 201 行的词条集,按四条轴分组,每个词条带定义和
Avoid(避免使用的近义词)列表。
这个分工本身就是它自己原则的一次演示——把不需要每次都读的内容压到链接文件里,
第 7 节的渐进披露会细讲。
SKILL.md 里有一句自我描述:「This skill is all reference.」
意思是它通篇是 reference(参考材料:按需查阅的定义、规则、事实),
没有 steps(步骤:要 agent 按顺序执行的动作)。
所以用它不是「跑一遍流程」,而是「对照着查」——查词汇、查原则、查失败模式,
然后回去改你手里那个 skill 的文本。
人读文档版列了四个典型时刻:决定一个新 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.md (aihero.dev/skills-writing-great-skills)
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 可预测了,这两样自然跟着变好。
出处:SKILL.md 开篇 · GLOSSARY.md 的 Predictability 词条
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-invocation,agents/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 一节里那一行「点名 + 何时用」。
本仓库有一份这一轴的「应用版」:.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
一个 model-invoked 的 description 干两份活:说清这个 skill 是什么,
再列出应该触发它的 branch(分支:这个 skill 被使用的不同情形,
不同运行会走不同路径)。description 的每个词都在涨 context load,
所以它比正文更值得狠删。SKILL.md 给了三条规矩:
看一个本仓库的真实样本。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)
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
Progressive disclosure(渐进披露)就是沿梯子往下挪的那一刀:
把 reference 挪出 SKILL.md、挪进链接文件,让顶部保持可读。
机制很朴素:skill 目录里放一个按内容命名的 .md 文件——
本 skill 把全部完整定义披露给 GLOSSARY.md,
codebase-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(撒开)是同一个意思碎在很多处——前者合并,后者收拢,治法不同。
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 词条
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 一节
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 | wayfinder(0016) |
地图故意不完整:看得见却还不能精确提问的区域留在雾里,frontier 推进时雾再毕业成 ticket |
| lesson / zone of proximal development | teach(0021,下一课) |
一节课教一件紧贴 mission 的小事,落在学习者的最近发展区里——你现在读的这个 HTML 就是这个词的产物 |
这不是巧合。Leading word 的 invocation 锚定作用要求同一个词住在 prompt、docs、代码里——这套仓库的 skill 共享一小批词,所以互相触发才可靠。 原文最后一句是个行动号召:假设每个 skill 都揣着能被 leading word 退休掉的复述——去找。双赢:token 更少,思维的钩子还更尖。
出处:SKILL.md 的 Leading words 一节 · GLOSSARY.md 的 Leading Word 词条 · 住处验证:diagnosing-bugs · to-tickets · wayfinder · teach
修剪(pruning)是保持 skill 苗条的日常纪律,三查按顺序过:
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 词条
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:直接描述目标行为,让被禁行为从未被说出口;无法正面表述的硬护栏才保留禁止,且必须配对「那该怎么做」 | — |
它是一个 between-steps failure(步与步之间的失败)—— 需要 steps 才发生;一个没 steps 的 skill 早早收工,不算 premature completion, 算判据的 demand(要求度)没吃够导致的 thin legwork。判别清楚了再下药。
它是一场拔河,两边各一股力: 拽着 agent 往前冲的是可见的 post-completion steps—— 后续步骤在上下文里露得越多,拉力越强; 抵抗的是 completion criterion 的清晰度—— 判据又硬又可检验,看见再多后续也扛得住。 所以模糊是必要条件:判据够硬的步,根本不需要防御。
防御顺序是固定的,别跳步: 先磨判据(cheap, local——改一句话的事); 只有判据「不可约地模糊」(这件事的完成标准本质上没法写得更硬), 并且你真的观察到了赶工,才动第二根杠杆: 按序列拆,把后续步骤藏起来。
/handoff 换个新会话,0006),
或者一次 subagent 派出(子代理拿到的是裁剪过的上下文)。
Inline 的 model-invoked 调用不算:被拉的 skill 内容进了同一个窗口,
后续步骤还在上下文里,什么都没清掉。
这正好解释了主 flow 的 context hygiene 为什么要求每个 /implement
在干净上下文里开跑(0011)——那不是洁癖,是 premature completion 的防御工事。
「Don't think of an elephant」(别想大象)——这句话一出口,大象就占满了脑子。 否定式导向适得其反的机制是:否定是个弱修饰词,会被强激活的概念碾过去。 你写「never write verbose comments」,agent 刚读到的模式是 verbose comments——禁令有一半会被读成指令。 GLOSSARY 甚至给这个被点名的东西起了个 leading word:elephant, 凡是禁令点名叫进画面里的,都是大象。
解法叫 prompt the positive(提示正面): 直接描述目标行为(「write one-line comments」),让被禁行为从未被说出口。 禁止只在一种情况下挣到位置:无法正面表述的硬护栏; 即便那时,也必须配对一句「那该怎么做」,让注意力落在目标上而不是禁令上。
出处:SKILL.md 的 Failure modes 一节 · GLOSSARY.md 的 Premature Completion / Post-Completion Steps / Duplication / Sediment / Sprawl / No-Op / Negation 词条
上一课类型的「谁引用它」表,对这个 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 写作」这个领域上 |
拿它自己的原则逐条自检,几乎全中——读它等于读一份「原则落地示范」:
GLOSSARY.md,
正文第一句就是 context pointer:「加粗术语的定义在 GLOSSARY.md」——
你碰到 bold 词需要全文时,pointer 触发。
| 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
0001 的全表写得明白:「什么都不改(纯参考文档)」。
它不写文件、不动 issue tracker、不碰任何 skill。
真正的副作用发生在你对照它动手的时候——编辑落在目标 skill 的文件上:
SKILL.md 的正文、frontmatter 的 description、
sibling 披露文件、agents/openai.yaml。
记账时别把这笔账记到它头上。
这是「推荐下一步」在本仓库的具体化。你在本仓库里新增、改名、改行为一个 skill 之后,
根目录 AGENTS.md 规定了一串必须跟着动的位置——
这串清单本身就是 single source of truth 思想的应用(每样东西有一个权威出处,其余同步):
.claude-plugin/plugin.json 的 skills 数组——已发布集合的唯一权威出处;新增/删除 skill 必动。README.md 和所在 bucket 的 README.md——promoted bucket(engineering / productivity)里的每个 skill 必须有条目,名字链到它的 SKILL.md,并按 User-invoked / Model-invoked 分组。docs/<bucket>/<skill>.md 文档页——promoted bucket 的 skill 有人读文档,行为变了要按 .agents/writing-docs.md 重新同步。ask-matt 的 SKILL.md——user-reachable skill 新增、改名、删除或改了在 flow 里的位置时,必须重读并更新路由;「路由器说谎」是 AGENTS.md 点名的反模式。scripts/link-skills.sh——增删改名后重跑,保持本地软链最新。claude plugin validate . --strict。ask-matt(0019);它路由不了「改 skill」的问题,但能路由「干活」的问题。两个方向:这个 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.yaml 的 policy,两份同步改(机制见 .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」 | 别把禁令加粗加叹号——强调只会把大象喂得更壮 |
先别往回翻表,凭记忆答。选项的长度刻意对齐,不会从版式泄题。术语以本课和 SKILL.md / GLOSSARY.md 的精确定义为准。
本课主一手材料(请打开原文读,不要只背本页摘要——83 + 201 行,一次能读完):
skills/productivity/writing-great-skills/SKILL.md
—— 原则正文:invocation、description、信息层级、拆分、修剪、leading words、失败模式。本课首选 primary source。
…/GLOSSARY.md
—— 全部词条的完整定义和 Avoid 列表;本课的每个术语都能在这里查到更硬的版本。
docs/productivity/writing-great-skills.md
—— 给人看的叙事版(aihero.dev/skills-writing-great-skills):两种 load 的引入讲得最缓。
速查页(本课同步): reference/writing-great-skills.html
导航: 上一课 0019 ask-matt (router 概念的肉身——第 4 节的 router skill 就是它)。 总览仍回 0001 系统地图; 平行的词汇地板课见 0004 和 0005。
建议下一课(0021,并行编写中):
teach——这套课程的生产者,
也是 leading word 的活案例库(lesson、zone of proximal development 都是它的词)。
和本课的交接点:读 teach/SKILL.md 时顺手做第 9 节的猎捕练习——
数数它用了几个 leading word、哪些句子其实通不过 no-op 测试;
用刚学的词汇读一个真实 skill,比再做十道选择题更固化。
SKILL.md / GLOSSARY.md 的原文,不会临场编造。
做完检索练习后,回复「练习结果 / 哪里卡住 / 开 0021 或先补 0019」,我们安排下一课。