LeMetaSkill v1.1.0:跨 runtime(ZCode/Claude Code/Codex)的 Agent Skill 创建与迭代工坊

- SKILL.md 双工作流(创建/迭代)+ 两道门(验料/通用化)+ 三档位
- 7 篇方法论 references + 3 个纯标准库脚本(scaffold/validate/trigger_eval)
- 自身触发用例 16 条 + 先例研究/创建/迭代证据报告
- 方法论吸收自 qiaomu-meta-skill 与 luban-skill,取舍见 reports/prior-art.md
This commit is contained in:
Leroy
2026-10-05 12:09:22 +08:00
commit d3e9bd45bd
21 changed files with 1827 additions and 0 deletions
@@ -0,0 +1,47 @@
# 目录架构——资源放哪,纪律是什么
Skill 是一个目录,`SKILL.md` 是唯一入口。其余一切按"模型什么时候需要它"分层。
## 标准布局
```text
<skill-name>/
├── SKILL.md # 必需。路由 + 最简工作流,≤500 行
├── references/ # 判断类知识:方法论、决策树、评分表。正文说"做 X 前读 references/x.md"
├── scripts/ # 确定性工具:体检、测试、脚手架。能算的不让模型目测
├── evals/ # 回归用例:触发用例、输出样例。改动前后都跑它
├── assets/ # 模板、占位物:起草时复制出去改,本身不被读进上下文
└── reports/ # 运行证据:触发报告、handoff、迭代记录。给未来复查用
```
## 三层加载模型
1. `name` + `description`:常驻上下文,必须精短。
2. `SKILL.md` 正文:触发后加载,≤500 行预算。
3. `references/` 等附属文件:模型按需读取,原则上不限大小。
判断一个文件该不该存在,就看它能不能明确回答:**它提高了哪方面的稳定性?**
| 资源 | 提高的稳定性 | 不该存在的信号 |
|---|---|---|
| references/x.md | 判断质量 | 内容可以内联进正文而正文仍 <300 行 |
| scripts/x.py | 确定性、可回归 | 逻辑靠模型目测也能一次做对 |
| evals/*.json | 可回归 | skill 从不修改、或无触发风险 |
| assets/* | 起草一致性 | 从不新建同类产物 |
| reports/* | 证据、可复查 | 一次性过程记录,没人会回头看 |
## 资源纪律
- **不造仪式性目录。** 档位用不到的目录不建;scaffold 生成的空目录里要有 README 说明用途或干脆删掉。
- **不重复表达。** README 面向安装者,SKILL.md 面向模型——两份内容各说各的话,不互相复制。
- **正文引用必须可达。** 正文里出现的每个 `references/xxx.md` 链接都要真实存在(`validate_skill.py` 会检查悬空引用)。
- **单一入口。** 一个 skill 一个根 `SKILL.md`;内嵌的示例/fixture 用 `SKILL.example.md` 命名,避免被当成第二个入口发现。
- **密钥与私有路径零容忍。** 任何文件里出现 API key、token、私有绝对路径(`/Users/<你的用户名>/…`)都是 FAIL。
## 与档位的对应
- **draft**:只有 `SKILL.md`。其余都不建。
- **shared**:+ `evals/trigger_cases.json` + README(价值钩子、触发方式、安全边界三节起步)。
- **rigorous**:+ `references/` 分层 + `scripts/`(若有确定性工作)+ `reports/` 证据。
升级档位时按需补件,不提前预支。
@@ -0,0 +1,73 @@
# 交付报告——handoff 怎么写
创建或大幅修改 skill 后,用这个结构交付。报告要**短到能在最终回复里读完**,rigorous 档同步存 `reports/creation-handoff.md`(或 `iteration-<日期>.md`)。
## 报告结构
### 1. 结果
- skill 名、档位、一句话职责
- 安装路径
- 本次做了什么(创建 / 迭代了哪个面)
### 2. 参考学习(做了先例研究时)
列出 2–4 个真正看过源码的候选(搜索结果里瞥过一眼的不算):
- 名称 + URL/路径
- 为什么入选
- 学到的具体机制
- 该机制落在新 skill 的哪个位置
### 3. 取舍
- **保留**:原样吸收的机制
- **改造**:为 Leroy 的 runtime 环境(ZCode/Claude Code/Codex)改过的机制,写怎么改的
- **舍弃**:看过但没采用,写具体理由
- **原创**:先例没有、这次新造的
### 4. 亮点与证据
每个亮点三选一标注,不许裸奔:
| 标签 | 含义 | 允许的说法 |
|---|---|---|
| `[设计优势]` | 源码里看得见的设计选择 | "相比看过的候选,本包显式做了 X" |
| `[已验证]` | 有触发/输出/实测证据支撑 | "触发用例 8/8 通过(reports/trigger-eval.json)" |
| `[假设]` | 合理但未证明 | "预期能减少误触发,但缺实测证据" |
不写"最好""比 X 强"——没有公平对比就不许下比较级结论。清单差异不等于效果优势。
### 5. 验证与边界
- `validate_skill.py` 结果
- 触发测试结果(冒烟 + 实测;实测没做就写「实测证据缺失」)
- 已知的用例失败项
- 刻意排除的职责
## 紧凑模板
```markdown
已交付:<skill>(<档位>)— <一句话职责>,装在 <路径>
参考学习
- <候选A>:学到 <机制>;落在 <位置>。
- <候选B>:学到 <机制>;落在 <位置>。
取舍与原创
- 保留:… / 改造:… / 舍弃:…(理由)/ 原创:…
亮点与证据
- [设计优势] …
- [已验证] …
- [假设] …(证据缺失)
验证:体检 <PASS/WARN…>;触发 <n/n>;实测 <结果或缺失>
边界:<不做的事、已知失败项>
```
## 诚实条款
- 「证据缺失」是合法状态,写出来不丢人,编造验证才丢人。
- 计划中的工作不是证据。
- 分数是预估就标"预估",跑过实测才能去掉标注。
@@ -0,0 +1,56 @@
# 意图工坊——接单与验料
目标不是做问卷,而是避免把一个模糊想法过早包装成错误的结构。用户已经给了足够信息时,直接做,并在动手前写出自己的假设。
## 什么时候需要问
- 用户只给了粗想法,还没说明输入和输出。
- skill 可能被别人复用(档位至少 shared)。
- 触发边界和相邻请求容易混(比如"优化提示词"vs"优化 skill")。
- 用户给了参考项目、竞品或长对话,需要先圈定借鉴范围。
## 必须捕获的七要素
1. **重复任务**:它要长期接住哪一类反复出现的工作。
2. **输入**:用户实际会丢给它什么材料(文件、链接、一句话、目录……)。
3. **交付物**:做好后交回什么——文件、报告、改动、结论。
4. **排除项**:哪些相近请求**不该**触发它(负触发,写进 description)。
5. **首要标准**:速度、一致性、可审计、跨项目,哪个优先。
6. **参考**:有没有要对标的公开项目;只借结构和方法,不复制表达。
7. **已有资产**:现成的脚本、模板、旧 skill、笔记、样例在哪,能直接收编什么。
七要素里最容易被跳过的是**排除项**——而它恰恰是触发不误伤的关键。
## 中文开场方式
适合模糊请求:
> 我们先不急着定结构。你先像聊天一样说说:这个 skill 以后最想帮你稳定接住哪类重复工作?你通常会丢给它什么材料?它最后交回什么结果才算好用?
适合目标明确的请求:
> 我按可复用 skill 来做。默认假设:它要接住的重复任务是 X,输入是 Y,交付 Z,不做 A/B。假设不对的话我动手前先改。
## 停止追问的标准
当你能写出一句**可防守的能力描述**时,就停止追问:
```text
这个 skill 接收 <真实输入>,用于 <重复任务>,输出 <可交付结果>,不处理 <相邻但不该触发的请求>。
```
不要为了把结构做完整而继续问不影响设计的问题。
## 验料三问(来自工坊第一道门)
| 问题 | 通过信号 | 不通过的处置 |
|---|---|---|
| 重复性 | 这类任务已出现 ≥3 次,或可预见高频出现 | 保留为对话步骤,等重复出现后再收编 |
| 稳定性 | 流程能写成固定步骤,判断点可枚举 | 拆出稳定子流程单独做,其余留对话 |
| 增益 | 能说清比现场对话强在哪(一致性/触发/携带资产/沉淀) | 没有增益就不做,直说 |
三个都过 → 好料。部分过 → 料可用,先调整定位(缩小职责到能过三问的子集)。重复性或增益不过 → 朽木,停手,给替代方向。
## 从对话历史里提取
用户说"把我们刚才做的这个变成 skill"时,先从对话里提取:实际用的工具、步骤顺序、用户做过的纠正、输入输出格式。这些比用户事后口头描述的"理想流程"更真实——按实际发生的行为建模,再让用户确认删减。
@@ -0,0 +1,74 @@
# 迭代工坊——改进已有 Skill
改一个 skill,比新建一个更容易翻车:它已经有用户(哪怕用户只有 Leroy 自己),改坏了触发就断了。迭代的核心纪律是**可回退、可比较、单面推进**。
## 第一步:冻结基线
动任何刨子之前:
- 有 git:开分支或记录当前 commit;
- 没 git:`cp -r <skill> <项目根>/.baseline/<skill>-<日期>/`。
两条纪律(实战教训):
1. **基线必须放在发现路径之外。** 放进 `.agents/skills/` 或 `~/.claude/skills/` 里的基线副本会被 runtime 当成另一个 skill 发现,制造幽灵触发。
2. **复制完立即验证。** `head` 一下基线的 SKILL.md 确认是旧版本——有些执行环境里文件写入跨调用不可靠,没验证过的基线等于没有基线。
之后所有候选改动都与基线比。基线是裁判,不是怀旧品。
## 第二步:诊断三把尺
| 尺 | 量什么 | 怎么量 |
|---|---|---|
| 结构尺 | 写得清不清楚 | `python3 scripts/validate_skill.py <目录>`,FAIL/WARN 直接转差距条目 |
| 触发尺 | 该触发时触不触发、不该触发时误不误伤 | `python3 scripts/trigger_eval.py <目录>` + 真实对话原话抽测 |
| 活体尺 | 真实任务里跑不跑得出结果 | 拿 2–3 个真实任务实际用一遍。"看起来能触发"不等于"跑得出结果"——静默失败比文档烂致命 |
**活体尺最常被跳过,也最值钱。** 大部分真问题(输出格式其实不稳定、某个步骤总卡住、引用的脚本跑不通)只有真实运行才暴露。
## 第三步:六维评分,定位最该刨的面
每维 0–10 分,**每个分数必须给证据**(哪条用例、哪次运行、哪行源码),凭手感打分作废:
| 维度 | 权重 | 量什么 |
|---|---:|---|
| 触发与边界 | 25 | description 覆盖、负触发、误伤/漏触发记录 |
| 可执行具体性 | 20 | 步骤是否可直接照做、示例是否字面可用 |
| 工作流清晰度 | 15 | 分步结构、何时读哪个 reference |
| 失败模式与停手点 | 15 | 出错怎么办、何时问用户,有没有编码 |
| 实测表现 | 15 | 活体尺结果 |
| 资源纪律 | 10 | 有没有不承重的文件、悬空引用、超长正文 |
总分不是用来攀比的,是用来**排序**的:最低分且权重高的维度,就是本轮唯一要刨的面。
## 第四步:单面慢刨
- 一轮只改一个面(只修触发、或只重构工作流、或只补失败模式)。
- 用户批量授权("都修了吧")后,升级为**单面单提交**——每个改动独立过验证门,绝不把两个面塞进一次改动。
- 改动前先写下:本轮只刨 X;改动边界:只改 X,不动 Y;预期提升是什么。
## 第五步:验证门
候选改动**全部满足**才保留,否则回刀(恢复基线,重新想):
1. 比基线**多通过**至少 2 条测试原话(触发用例或真实任务);
2. 没有把 skill 写得更长但更难用——行数增加必须换来可执行性;
3. 没有引入私有路径、密钥、不可复现依赖;
4. 没有破坏原有通过项——基线能过而现在过不了的,是退化;
5. 通过 `validate_skill.py` 全绿。
验收时换**独立验收视角**:假装是第一次见到这个 skill 的陌生模型,只读交付物,不知道改动过程。刨子和尺子不能握在同一只手里。
## 第六步:交付与回炉
交付改动报告(改了哪个面、验证证据、行数变化),并留**回炉清单**:
- 本轮"不做"的事和理由(下一轮入口);
- 已知边界损耗(哪些用例还是过不了);
- 沉淀机会:这次手写的验证手段,值得固化成 `scripts/` 工具或 `evals/` 用例吗?值得就顺手沉淀——验证不是脚手架,是交付物的一部分。
## 迭代时机
- 用户带着"它又翻车了"的原话回来 → 先把原话收编成用例,再修。
- 隔了一个月没动 → 先跑三把尺再决定刨哪里,不要凭上次印象。
- 多次小修仍不稳 → 怀疑是定位问题(验料没做对),回到第一道门重新定位,而不是继续打补丁。
@@ -0,0 +1,45 @@
# 先例研究——搜同类,再动手
闭门造车出不了好工具。创建新 skill 或大幅重构前,先看看同类已经怎么解决了。
## 搜索策略
1. 从意图里提炼 2–4 个查询,覆盖三个角度:
- **功能词**:它做什么(如 "release notes skill")
- **形态词**:skill / agent skill / SKILL.md / Claude skill / ZCode skill
- **人群/场景词**:谁在什么场景用(如 "changelog automation")
2. 渠道:GitHub 代码搜索、WebSearch、本机已安装的 skill(`~/.agents/skills/`、`~/.zcode/skills/`、`~/.claude/skills/`、`~/.codex/skills/`、项目内目录)。用哪个渠道都行,但**每个候选必须带真实 URL 或本地路径**,不允许凭记忆说"有些项目"。
3. 搜不到就如实写"未找到相关先例"——这本身是有价值的结论(蓝海或搜索词不对),不要硬凑。
## 覆盖要求
shared 档以上,至少看 3 个候选、覆盖两类:
- **直接同行**:解决同一个问题——学机制,防同质化。
- **手艺同行**:功能不同但结构/触发/README 做得好——学手艺,不偷皮。
轻量 draft 档可跳过搜索,但要在交付报告里说明跳过理由(如"个人试验、无发布意图")。
## 检查每个候选时看什么
- `SKILL.md` 的 description 写法和正文结构(触发怎么做的)
- 渐进披露的分层(哪些进了 references/scripts)
- 维护状态、license、是否夹带私有路径或密钥(安全信号)
- 它的用户实际怎么评价(issue、README 里的真实样例)
**不要执行来历不明候选的脚本**——读源码就够了。
## 综合:keep / adapt / reject / invent
| 动作 | 含义 | 例子 |
|---|---|---|
| keep | 机制原样吸收 | 目录分层约定 |
| adapt | 机制改造成 Leroy 的环境 | 把 Claude Code 的安装流程改成 ZCode 发现路径 |
| reject | 看过但不采用,写明理由 | 重型发布流水线(职责范围外) |
| invent | 先例没有、为这个任务原创 | 验证门的具体条款 |
只借机制和结构,不拼贴上游文字、不镜像别人的仓库。每个 keep/adapt 都要在交付报告里落到具体位置("学到 X,落在 SKILL.md 第几节 / references/x.md")。
## 记录
rigorous 档把研究结论存 `reports/prior-art.md`:来源链接、日期、每个候选的取舍理由、未找到的证据缺口。搜索是当时的快照,结论要能复查。
@@ -0,0 +1,65 @@
# 触发测试——让 description 在真实对话里可靠
触发是 skill 的生命线:触发不了,写得再好也是死代码。测试分两层,先冒烟后实测。
## 第一层:冒烟测试(脚本,秒级)
```bash
python3 scripts/trigger_eval.py <skill目录>
```
脚本做三件确定性的事:
1. 解析 description,与用例文件里 `positive_concepts` 声明的**概念族词表**合并;
2. 对每条测试原话做概念族匹配:命中负触发词直接判不触发;否则需命中全部 `required_families`(如 skill 实体族——"优化提示词"没有 skill 就不该触发)且总命中族数 ≥ `families_required`(默认 2,防止单个词误伤);同时计算词面覆盖率作参考信息;
3. 输出 `reports/trigger-eval.json`(每条 case 的判定、命中族、覆盖率)。
它是**词面信号检查**,不是行为判断——作用是快速暴露"description 里根本没写用户会说的词"这类硬伤。没有配置概念族的用例文件会退化为纯覆盖率阈值模式。
## 第二层:真实对话实测(必做)
冒烟全绿不代表会触发。在**新的对话轮**里,把测试原话当真实请求发给模型,观察:
- 该触发的原话,skill 有没有被加载、有没有按正文执行;
- 不该触发的原话,有没有误伤。
每档至少测:
- **应触发** 3–5 条:覆盖不同说法(口语/正式/中英混合)、不同入口(直接请求/丢来材料/求助式提问)。
- **不应触发** 2–3 条:相邻请求("优化这段提示词"vs"优化这个 skill")、一次性任务。
- **边界** 1–2 条:模糊但倾向触发的("这个流程每次都要重复讲一遍,烦死了")。
## 用例文件设计
`evals/trigger_cases.json` 的用例来自**用户真的会说的话**,不是设计师的语言。写用例时:
```json
{
"negative_patterns": ["不要做成 skill", "只要总结", "翻译一下"],
"should_trigger": [
{"text": "帮我把每周的周报整理做成一个 skill", "family": "cn_workflow"},
{"text": "turn this checklist into a skill", "family": "en_workflow"}
],
"should_not_trigger": [
{"text": "把这篇文章翻译成英文", "family": "translate_only"}
],
"near_neighbor": [
{"text": "帮我优化这段提示词", "family": "prompt_not_skill"}
]
}
```
- 每条标注 `family`,回归时按族看退化。
- 用例随真实误触发/漏触发事件增长:每次现场翻车,把那句话原样收编成用例——这是触发资产的本金。
- `near_neighbor` 是最值钱的一族:它们定义了边界。
## 判定与修复
- 漏触发 → description 缺场景词或写得太被动 → 补触发短语,重跑。
- 误触发 → 缺负触发 → 在 description 加"不要用于……",重跑。
- 修 description 而不是加规则正文——触发问题永远先在触发信号上修。
- 改完 description 必须全量重跑用例,防止按下葫芦浮起瓢。
## 记录
rigorous 档把实测结果记进 `reports/trigger-eval.json` 的 `live_turns` 段:每条原话、期望、实际、结论。没做实测就标注「实测证据缺失」,不假装做过。
@@ -0,0 +1,56 @@
# 写作手艺——description 与正文
Skill 的两个加载层各有各的写法:description 决定被不被触发,正文决定触发后好不好执行。
## description:唯一的自动触发信号
各 runtime(ZCode / Claude Code / Codex)都靠 frontmatter 的 `description` 决定何时加载 skill(连同 `name` 常驻上下文)。模型倾向于**漏触发**而不是误触发,所以 description 要写得主动一点。
**四件必须写进去的事:**
1. **做什么**:一句话职责。
2. **何时触发**:用户真实会说的话——"帮我做个 skill""把这个流程沉淀下来""给我的 skill 做体检"。给 3–8 条原话级别的触发词。
3. **负触发**:明确"不要用于……"的相邻请求。没有负触发的 description 会在边界请求上犹豫。
4. **丢来就触发**的说明:用户丢来 SKILL.md、目录、链接说"帮我看看"时该不该接。
**写法检查:**
- 用中英混合的真实口语测试:拿 5 条用户会说的原话(含 2 条不该触发的)逐条对照 description,每条都该能明确判出触发/不触发。
- 别写成功能清单("支持 A、B、C"),写成场景句("当用户想……时使用")。
- 长度:3–8 行。太短盖不住场景,太长稀释信号。
## 正文:给模型的操作手册
正文只在触发后加载,目标是让模型照着执行,而不是让人读了佩服。
**七条手艺:**
1. **祈使句**。"读取文件后再编辑",不是"你应该考虑读取文件"。
2. **讲为什么**。规则不明显时给理由——模型理解了原因才会在边界情况做对判断。发现自己在写全大写 MUST 时,通常说明该把理由讲清楚,而不是加重语气。
3. **示例胜过规则**。要求结构化输出就贴一个字面示例;要求调某工具就给调用样例。一段示例顶三条规则。
4. **正文 ≤500 行**。超了就把领域细节拆进 references,正文里留一句"做 X 前先读 references/x.md"。
5. **每节一个职责**。读者跳着读不迷路。
6. **失败模式要编码**。"遇到 X 时停下来问用户"比"小心行事"有用得多。
7. **写完删一遍**。删掉不承重的句子。规则越少,剩下的越有权威。
## 跨 runtime 约定(ZCode / Claude Code / Codex)
Skill 遵循 Agent Skills 开放格式:一个目录 + `SKILL.md`(frontmatter:`name` + `description`)。三个 runtime 都认这个格式,差别只在发现路径:
| runtime | 项目级 | 用户级 |
|---|---|---|
| ZCode | `.zcode/skills/`(优先)· `.agents/skills/` | `~/.zcode/skills/` · `~/.agents/skills/` |
| Claude Code | `.claude/skills/` | `~/.claude/skills/` |
| Codex | `.codex/skills/` | `~/.codex/skills/`(实验性) |
- **frontmatter**:`name`(kebab-case,1–64 字符,必须与目录名一致)+ `description` 是必填;其余保留字段按需。
- **新建默认放 `.agents/skills/`**——跨工具标准位;目标 runtime 不读这个位置时,复制或软链到它的目录(一份源,多处入口,改完同步)。
- **目录即身份**:同名 skill 不同路径算两个安装,ZCode 里路径优先级高的胜出——起名字前先查各 runtime 的发现路径有没有撞名。
- **可移植三禁**:正文不写死某个 runtime 专属的工具名/技能名(如把"配置排障"指给单一 runtime 的指南);不用私有绝对路径;脚本只用 python3/bash 标准库。做到这三条,同一个目录在三个 runtime 里行为一致。
- **先例研究时的提示**:搜 Claude 生态的 skill(数量最多)借鉴机制没问题,但安装路径、触发语法要按目标 runtime 换算,不要照搬。
## 命名
- 英文 kebab-case,≤3 个连字符段为佳:`weekly-report`、`api-docs-lint`。
- 名字要能自解释职责;人设名(如 `luban`)只有配合强 description 才可用。
- 与已有 skill 撞名 = 改名,不是覆盖。