zmm-skillify:把跑通的做法固化成技能
先读 config.yaml(读不到 → 明说配置缺失并停下,不用示例值假装是用户的设定),再读 zmm/references/交互规范.md(🔴 不是读一遍就算:收尾按 §四 三件套 —— Recap · Before/After · 下一步给编号选项;缺信息按 §四 用选择题问,一次只问一个;不适用的情况见 §五),再读 zmm/references/家族公约.md,再读记忆 {config.paths.memory}/zmm-skillify/ + _通用/。
本技能内置判据在 references/规则卡.md(判据 / 为什么 / 怎么查 / 强度),开工前读一遍;{vault} 里有对应的规则文件时以 vault 为准、规则卡为底。
🔴 门禁:没跑通过的,不许固化
本技能只从「已经产生过正确结果的过程」提炼。 进来先查三件事,缺任一 → 说明缺什么,停下:
| 查什么 | 不满足时 |
|---|---|
| 这次会话里真的做完了一件事吗 | 只有讨论、没有产出 → 「还没有可固化的东西,先把这件事做完」 |
| 结果被验证过吗(用户认可 / 有数据 / 有可检查的产出) | 没验证 → 「这套做法还没被证明有效,固化了等于把没验证的经验写成规则」 |
| 它会再次发生吗 | 一次性的 → 「这件事不太会重来,固化的收益是负的」——可以只留一份记录,不做技能 |
⚠️ 不许因为用户说「做成技能」就跳过门禁。 用户想要的是下次省事,不是多一个不准的技能。
从哪提炼:三个源,按可信度排序
- 本次会话的实际过程 —— 最可信。真做过、有产出、有反馈。
{config.paths.memory}里的技能记忆 —— 之前沉淀过的纠正与有效方法。- 用户口述的「我一般怎么做」 —— 🔴 可信度最低。人对自己流程的描述和实际做法经常不一样。 只能当线索,必须回到 ① 或 ② 找证据;找不到就在成品里标「未验证」。
三者冲突时以 ① 为准,并把冲突本身写进技能(「他说的是 X,实际做的是 Y,以 Y 为准」往往就是最值钱的那条规则)。
五步
Step 1 · 写出问题契约
反复出现的问题:
什么情境下会遇到:
这次是怎么解决的(按实际发生的顺序,不是理想顺序):
产出物是什么:
凭什么算做完了(可检查的证据,不是「感觉good」):
明确不处理的邻近问题:
🔴 「凭什么算做完了」写不出可检查的证据 → 停下。 一个没有完成判据的技能,下次没人知道它跑对没有。
Step 2 · 把「好用」翻译成可观察的行为
用户会说「要写得自然」「要判断准」。这些不能进技能,必须翻成能被检查的:
必须做到(可观察):
禁止出现(可观察):
允许它自己发挥的部分:
最容易出的那个错:
出错时应该怎样(停下问 / 降级 / 明说做不到):
对照:「判断准」❌ → 「候选必须从实际列出的清单里选,没列出来的不许编」✅
Step 3 · 定判据的可信度等级
家族公约要求每条结论标来源。新技能里的每条规则都要带一个等级:
| 等级 | 什么时候用 | 写法 |
|---|---|---|
| 🟢 实测 | 这次会话或历史里有具体case支撑 | 写清代价:「实测代价:整版重写」 |
| 🟡 推断 | 从实测推出来,但没直接验证过 | 必须补一句「如果这条错了,最可能错在哪」 |
| ⚪ 猜测 | 只是听起来对 | 默认不写进技能。非要写就标死,且不能当判据用 |
🔴 不许把 🟡 和 ⚪ 写成 🟢 的语气。 这是家族里最容易犯的错。
Step 4 · 生成技能目录并自检
zmm-<名字>/
SKILL.md 入口:门禁 + 主流程 + 停止条件 + 红线
references/ 条件性细节(只在某些情况下才读的)
scripts/ 重复且确定的活(能用脚本就别让模型算)
主入口保持轻:SKILL.md 只放每次都要走的;分支细节进 references/。
自检清单,逐条过:
- frontmatter 有
name(ASCII slug,跟目录名一致)、description(含中文触发词)、version - description 里写清什么时候该用它,不只是它能干什么
- 有门禁:什么情况下不该用它、该停下
- 每条规则带 🟢🟡⚪ 等级
- 有停止条件:做到哪算完
- 读了家族公约与交互规范,收尾给编号选项
- 跟现有 20 个技能没有职责重叠 —— 重叠就该改那个,不是新建一个
🔴 最后一条最容易漏。 先跑 bash zmm/scripts/list-skills.sh 看现有的,明确说出「它和 zmm-xxx 的边界是什么」。说不清 → 不该新建。
Step 5 · 让它跑一次再交(自检过了不等于能用)
上面的清单全是静态项:文件在、字段全、规则有等级。一个技能写完从没跑过就进技能目录,下次真用才发现门禁写得跑不通 —— 这和「写代码的人不能批自己的代码」是同一条纪律。所以交付前按下面的梯子往上爬,爬到哪级就只许说哪级的话:
| 级 | 做了什么 | 允许说的话 |
|---|---|---|
| 0 | 静态自检过 | 「文件齐了」。不许说「能用」 |
| 1 | 拿一个真实输入,在新开的 context 里按 SKILL.md 跑一遍,产出物符合问题契约的完成证据 | 「主场景跑通了」 |
| 2 | 跑了一组样本(见下),含至少一个近邻反例,执行者没看过答案 | 「能分清该做和不该做」 |
| 3 | 改过一版之后,重跑同一组样本,命中不低于上一版 | 「这版没退步」 |
样本怎么建(放技能目录 evals/,随技能一起走):
sample-NN-<描述>.md:给执行者的输入。sample-NN-答案.md:只给评分者,列「必须抓到」和「不许误报」两张表,每项 1 分- 一组至少三类:正例(该触发且该抓到的)· 边界(刚好在门禁上的)· 近邻反例(长得像但属于隔壁技能,或看着像问题其实不是)—— 22 个技能触发词互相重叠,近邻反例就是防误触发的
- 结果落
evals/results/sample-NN-v<版本>.md,evals/README.md记一张表:样本 · 版本 · 命中 / 满分 · 误报 · 结论。版本号指向 SKILL.md 的version,不许叫「最新版」 - 先手工跑,不写 runner。三个样本手工跑十分钟,够了
跑挂了先归类再改(不归类就一律往 SKILL.md 加规则,越加越长):
| 挂在哪 | 长什么样 | 改哪里 |
|---|---|---|
| 指令 | 规则在,执行者理解成了别的 | 改那条规则的措辞,加一个反例 |
| 触发 | 该进的没进 / 不该进的进了 | 改 description 的触发词与「不该用它」 |
| 输入 | 样本本身缺东西,谁来都做不了 | 改样本,或在门禁里加「缺 X 就停」 |
| 判据 | 答案本身有争议 | 先跟用户对答案,再动技能 |
| 波动 | 同一输入两次结果不同 | 规则给了空间没给判据,补判据 |
🔴 同一个失败连改三版还在靠「再加一条针对这个样本的规则」,停下:那不是规则缺,是这个技能的边界画错了,回 Step 1。
现成的例子:zmm-flow/evals/(重设计前后各跑一版,v0.1.0 与 v0.2.0 结果都在)、zmm-resonate/evals/、zmm-review/evals/(2026-09-06 建)。
交付边界
默认只做到本地可用:生成目录、放进用户的技能目录、告诉他怎么调。
🔴 发布是另一件事,必须用户明确要求才做。 包括:推公开仓库、发 ClawHub / SkillHub、加进打包版。 用户没说「发出去」,就不要碰这些 —— 一个刚成型的技能进公开渠道,改起来的代价比留在本地大得多。
停止条件
做到下面任一条就停,别继续加:
- 技能在新 context 里跑通问题契约里那个场景,且产出物符合完成证据(Step 5 第 1 级以上)
- 用户说够了
- 发现它和现有技能重叠 → 改那个,不新建
- 发现门禁没过 → 说明原因,不硬做
收尾
按〈交互规范·四〉:Recap(固化了什么)· Before/After(不做这个技能,下次要重新想哪些)· 下一步给编号选项。
顺手写一条记忆到 {config.paths.memory}/zmm-skillify/:这次固化的是什么、门禁是怎么过的、有没有踩到重叠。先查重。