# Dsh Skill Authoring

> 为 DSH 编写、修改和验证技能（SKILL.md）。包含官方 frontmatter 规范与技能根优先级、description 触发面写法、篇幅与拆分标准、以及「写完之后怎么证明它真的管用」的 A/B 验证流程。无论用户是要新建技能、改现有技能的正文或 frontmatter、给技能加 references 或 scripts、诊断「技能装了却不出现 / 不触发」、还是问技能该写多长、该不该拆文件、description 怎么写才触发得准，都要用本技能 —— 即使对方没说出 skill 这个词。看到 SKILL.md、技能目录、`.dsh/skills`、技能不触发、frontmatter 这类线索时同样适用。

- Skill: `gezi-wen/dsh-skill-authoring` (Agent Skill, multi-file: 3 files)
- Install (CLI): `npx skillmds@latest add gezi-wen/dsh-skill-authoring`
- Raw SKILL.md: https://api.skillmd.com/api/skills/gezi-wen/dsh-skill-authoring/raw
- Safety review: pending (external: skill-scanner PASS, skillspector PASS)
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- Author: gezi-wen (https://skillmd.com/u/gezi-wen)
- Updated: 2026-09-22
- Page: https://skillmd.com/skills/gezi-wen/dsh-skill-authoring

---


# 写 DSH 技能

技能是给未来的自己（或姐妹）看的工作手册。写它只有两个标准：**触发得准**、**照着做真的能做成**。其余都是围绕这两条的工程细节。

本技能服务两种用法：在笔记本上写技能，在远程服务器上读技能干活。所以每一步都要能在「看不到界面、操作者不在现场」的条件下走完。

## 一、动手前先分清三件事

### 1.1 哪些技能是官方的（判据，别看 UI 标签）

技能页上的「来源：filesystem」是**提供方名字**，不是归属 —— `dsh-skill-filesystem` 这个提供方同时供给用户根和官方内置根，UI 区分不了。

真正的判据是两条：

| 判据 | 官方随包 | 用户自装 |
|---|---|---|
| 组合里有没有 `bundledSkillDir` / `customSkillDirs` | 有内置根才可能有 | 无 |
| 技能目录的真实路径 | DSH 安装树内（如 `@deepseek-ai/dsh-agent-presets/presets/<preset>/skills/`） | `$DSH_HOME/skills/` |

查法：

```powershell
dsh --profile web --dump-default-config | Select-String -Pattern "skill-filesystem" -Context 0,6
Get-ChildItem "$env:DSH_HOME\skills" -Force          # 注意 -Force，漏了隐藏目录会误判
```

**这台机器的实情（2026-09-10 核）**：只有 cordis preset 随包发的 **2 个**技能（`cordis-plugin-development`、`editing-cordis-compositions`），经 preset 的 bundled 根（rank 600）进来。`$DSH_HOME/skills` 下那 20 个全是自装的。所以「DS 官方技能」目前只有 2 个 —— 想引用「官方做法」时，权威出处不是任何一个技能，而是 §二 的 README。

### 1.2 官方规范的权威出处

```
<DSH 安装树>/node_modules/@deepseek-ai/dsh-skill-filesystem/README.zh.md
<DSH 安装树>/node_modules/@deepseek-ai/dsh-skill/README.zh.md
```

**规范以它们为准**，不以任何技能为准 —— 包括本技能。本技能是规范的摘要 + 我们摔出来的经验；两者冲突时按 README 走，并把冲突记下来。

### 1.3 本技能与其它技能的分工

| 需求 | 用哪个 |
|---|---|
| 写/改技能、判篇幅、调 description | 本技能 |
| 诊断 DSH 起不来、技能加载失败、链接损坏 | `dsh-repair` |
| 写 DSH 的插件（不是技能） | `dsh-plugin-development` |

## 二、DSH 官方规范（摘自 `dsh-skill-filesystem` README）

### 2.1 文件格式与发现

技能是**被扫描根目录顶层**的目录 bundle `<name>/SKILL.md`，或平铺文件 `<name>.md`。**刻意不支持发现嵌套的 `**/SKILL.md`** —— 把技能埋进子目录等于没写。

### 2.2 frontmatter 字段

**必填**：`name`、`description`。
**可选**：`whenToUse`、`metadata`、`disable-model-invocation`、`user-invocable`。

| 字段 | 作用 |
|---|---|
| `disable-model-invocation: true` | 把技能从**面向模型的目录和 loader** 中排除（人还能用，模型看不到） |
| `user-invocable: false` | 从**面向用户的命令**中排除 |
| 省略 | 对应接口默认允许 |

这两个键接受 YAML 布尔值，以及不区分大小写的 `true`/`false`、`yes`/`no`、`on`/`off`、`1`/`0`。

**被拒绝的拼写或非布尔值会让整个 skill 随警告一起被丢弃 —— 而不是静默允许某个接口。** 所以 `disable-model-invocation: off` 是合法的，`disable-model-invocation: nope` 是致命的。

### 2.3 目录与正文有独立的生命周期

发现阶段把 frontmatter 解析进目录条目；**每次加载都重新读取当前文件**。所以改正文不需要版本化或缓存失效 —— 存盘即生效（下一个模型步骤）。

### 2.4 根与优先级

按 rank 顺序扫描，**数字小的先命中**：

| Rank | 来源 | 路径 |
|---|---|---|
| 100 | `project-dsh` | `<projectRoot>/.dsh/skills` |
| 200 | `project-agents` | `<projectRoot>/.agents/skills` |
| 300 | `custom` | `Config.customSkillDirs` |
| 400 | `user-dsh` | `<dshHome>/skills` |
| 500 | `user-agents` | `<agentsHome>/skills` |
| 600 | bundled | 配置了 `bundledSkillDir` 才有 |

项目根是**包含 `.git` 的最近祖先目录**；不存在则用当前 cwd。用户 DSH 根会**跳过其 `.system` 子目录**（那是预留区）。

**实践含义**：同名技能可以靠 rank 覆盖 —— 项目级（100）压过用户级（400）。要在某个项目里临时改掉某个技能的行为，放一份到 `<projectRoot>/.dsh/skills/<同名>/` 即可。

### 2.5 变更检测

现有根被监视。**新增、改名、删除技能，或编辑它的 frontmatter**，都会在下一个模型步骤触发目录刷新。

`references/`、`scripts/`、`assets/` 等 bundle 资源下的编辑**不触发**刷新（因为正文每次加载都重读，资源本来就该在用时才读）。

第一方的 `write` 与 `edit` 工具命中受监视的技能时会直接使提供方失效，所以模型不必等宿主 watcher 就能看到自己的改动。外部 IDE / Git / shell 的改动由宿主 watcher 捕获。

### 2.6 失败长什么样（最容易被骗的一节）

> 缺少有效 frontmatter、名称无效或调用值无效的文件**会随警告被跳过**，因此**模型目录不会收到逐 skill 诊断，也无法区分缺失的 skill 与无效的 skill**。

这句话是本节最贵的知识。它意味着：**技能"不见了"，你无法从模型侧判断它是被删了、路径变了、还是 frontmatter 写坏了。** 唯一可靠的排障手段是 §四 的静态校验脚本 —— 别靠"重启试试"。

### 2.7 YAML 标量的两个静默杀手：`:` 与 `#`

frontmatter 是未加引号的 YAML 标量。两个元字符会出事，**症状完全不同**，所以别只防一个：

| 字符形态 | 机制 | 症状 |
|---|---|---|
| `: `（半角冒号 + 空格） | 开启嵌套映射 → **解析失败** | 技能从目录里**消失**，没有任何报错（§六 事故一，2026-09-10 实测） |
| ` #`（前面有空格的 `#`） | 被当**注释起始符**，后半句整段吞掉 | 技能**还在**、照常加载，但字段被悄悄截断 —— 如 `React #31` 之后的内容全丢（§六 事故三，2026-09-17 实测） |

`#` 这条更阴：解析成功、技能照常进目录，只是触发面残缺，页面和日志里都没有任何提示。YAML 规范要求注释由**空白之后**的 `#` 引出，所以 `React#31`（`#` 前无空格）不会被吞 —— 2026-09-17 在本机 yaml 包上实测确认。

**修法**：长文本（description、whenToUse）要么整个加引号 —— 单引号最省事，`'…React #31…'` 实测能完整保留 —— 要么避开 `: ` 与 ` #` 这两个形态。更省心的规矩是：**写 frontmatter 时默认 YAML 会吃字符，改完必须解析并断言字段完整（§4.1），不靠肉眼。**

## 三、黄金铁律

1. **description 里既不能出现 `: `（半角冒号+空格），也要当心 ` #`。** frontmatter 是未加引号的 YAML 标量：`link: xxx` 让解析失败 → 技能**静默消失**；`React #31` 这种 `#` 前带空格的写法则是**解析通过、后半句被当注释吞掉**（§2.7）。要么用全角「：」/避开这两个形态，要么给整个值加引号。改完必须解析并断言（§4.1）。
2. **改 frontmatter 前先备份整个技能目录。** frontmatter 是"热"的（§2.5），改坏了立即从目录里消失；没有备份就只能重写。
3. **`name` 一旦定下就别改。** 改名等于换了个技能：旧名从目录消失、用户调用路径失效、别的技能里对它的引用全部悬空。
4. **判定"技能装了却不出现"先跑静态校验，不要先怀疑 DSH。** §2.6 说了模型侧拿不到诊断。
5. **description 是唯一的触发机制。** 正文写得再好，description 不含触发线索就等于没这个技能。系统提示里只有 name + description 进模型视野。
6. **技能必须写过测试才算写完。** 见 §五 —— 只读一遍觉得没问题不算验证。
7. **篇幅控制在 300–500 行**（一条实践约定，2026-09-10 定的基线）。低于 300 行往往漏了边界情况；超过 500 行说明该拆 `references/` 了。
8. **派子 agent 做技能测试/审计时，把扫描范围写成白名单。** 明写「禁止递归 `node_modules` / `.pnpm` / lockfile」，否则它会扎进依赖树烧掉几百万 token（见 §六 事故二）。
9. **只改私有原件（`$DSH_HOME/skills/<name>/`），不拿发布副本当工作区。** 发布副本是脱敏后的产物：它不在任何技能扫描根里（§2.4），改它既不影响本机行为、也不会上线。详见 §九。
10. **同步副本进公开发布物之前，必须跑一遍禁用词扫描。** 2026-09-13 实测出过真泄漏 —— 已发布的公开产物里带着本机绝对路径、真人名、内部称呼（§九）。

## 四、静态校验（写完立刻跑）

本技能自带 `scripts/check-skill.js`，一次查五件事：

```bash
node <本技能目录>/scripts/check-skill.js "$DSH_HOME/skills/<技能名>"
```

它检查：

1. **frontmatter 能否被 YAML 解析**（事故一的直接产物）—— ⚠️ 它只拦得住「解析失败」和 `: `；**`#` 那类"解析成功但字段被吞"的静默截断它查不出来**（§2.7），得靠 4.1 单独断言
2. **必填字段在不在**、`name` 是否与目录名一致、布尔字段是否合法拼写
3. **正文里引用的 `references/` `scripts/` 文件是否真实存在**
4. **站内锚点 `](#xxx)` 与正文里的 `§N` 是否指向真实标题**（标题改了忘改链接是常见腐烂）。⚠️ `§N` 只在**本文件**里找——所以「见 REFERENCE `§4`」这种跨文件引用会被误报成「交叉引用找不到对应章节标题」（2026-09-12 在 `dsh-plugin-development` 上实测）。要指别的文件的章节，就写章节全名或文件名，别用 `§N`；**实在要举例，把 `§N` 放进行内代码里**（脚本会剔除代码再扫描）。代码块内的 `§N` 同样不检查。
5. **行数**是否落在 300–500 的建议区间

退出码非 0 就是有问题。**加 `--json` 可给自动化流程吃结果。**

> 为什么必须静态校验而不是"重启看看"：§2.6 —— 无效技能被跳过时模型侧无法与"缺失"区分，重启只会让你看到同样的"不见了"。

### 4.1 断言 frontmatter 字段完整（补 `#` 这类静默截断）

解析成功 ≠ 字段完整。改完 frontmatter 后跑一遍（2026-09-17 实测，本机 yaml 包）：

```powershell
node -e "const fs=require('fs'),y=require(process.env.DSH_HOME+'/profiles/node_modules/yaml');const fm=fs.readFileSync(process.argv[1],'utf8').match(/^---\r?\n([\s\S]*?)\r?\n---/)[1];const m=y.parse(fm);for(const k of ['name','description'])if(!m[k])throw new Error('缺 '+k);for(const l of fm.split(/\r?\n/)){if(/^[A-Za-z0-9_.-]+:/.test(l)&&/ #/.test(l))throw new Error('未加引号的值里有 # 会被当注释吞掉: '+l)}console.log('frontmatter OK: '+Object.keys(m).join(', '));" "<技能目录>\SKILL.md"
```

它做三件事：**真 YAML 解析**、必填字段非空、**逐行检查未加引号的值里有没有 ` #`**（注释起始符的形态）。退出码非 0 就是有截断。

`yaml` 包的位置随 DSH 安装树变：`check-skill.js` 的 `loadYaml()` 里那串候选路径是权威写法，换机器时照它改。

## 五、验证技能真的管用

静态校验只证明"文件合法"，不证明"照着做能做成"。后者必须做行为验证。

### 5.1 A/B 对照（唯一诚实的做法）

技能的价值 = **带它**与**不带它**做同一件事的差距。所以：

1. 写 **2–3 个真实的、具体的**测试 prompt（不是"格式化数据"这种抽象话，要带路径、背景、口语化措辞）。
2. **同一轮**派两组子 agent —— 一组带着技能路径，一组不带（或带旧版快照）。同轮派发，别先后。
3. 对比产物，而不是对比它们的自我报告。
4. 空结果、跑偏、只做对一半，都算不过；据此改技能再跑下一轮。

技能的基线随类型不同：**新建技能**用"完全不给技能"；**改现有技能**用"改之前那份快照"（先 `robocopy` 一份出来当基线）。

### 5.2 派子 agent 的纪律

- 给每个子 agent**写死**：任务边界、扫描白名单、交付格式、产物落盘路径。
- 明写「禁止递归 `node_modules` / `.pnpm` / `pnpm-lock.yaml` / 打包产物」。
- 要它**带证据回报**（`文件:行号` 或命令输出），没取到证据的必须标「未取证」。
- 子 agent 会盲信自己写的总结 —— 交付前抽查它的证据链，别 blind-trust。

### 5.3 什么时候可以不跑 A/B

只改错别字、只改注释、纯排版调整，跑静态校验就够。**只要改了 description 或正文的判定逻辑，就得跑。**

## 六、真实事故

本节的复盘按 §7.6 的约定处理：结论留在这里，长到会稀释主流程的完整复盘才另建 `references/case-YYYYMMDD.md`。

### 事故一 · frontmatter 里的一个冒号，让技能消失（2026-09-10）

给 `dsh-repair` 扩写 description 时写进了 `mounted with link: that cannot reach...`。半角冒号+空格在未加引号的 YAML 里开启了一个嵌套映射 → 解析失败 → **技能立刻从技能目录里消失，没有任何报错指向原因**。

修法是删掉那个冒号；watcher 热加载让它自动回来。
**教训**：改 frontmatter 前后各跑一次 `check-skill.js`；改前先备份。

### 事故二 · 派子 agent 审计，烧掉 5.5M token（2026-09-10）

派子 agent 审计五个插件对 DSH 新版兼容性，提示词只写了「下载包对照 + grep 插件源码」，没锁范围。它扎进 `.pnpm` 私有副本和 131 KB 的 lockfile，**烧了 5.5M token 还没交报告**，最后被中止。那份审计换成定点 grep 十分钟就做完了。

**教训**：§5.2 的纪律不是形式主义 —— 扫描范围要写成**白名单**，不是描述意图。

### 事故三 · `#` 吞掉 description 的后半句（2026-09-17）

复核 frontmatter 时发现某个技能的 description 只剩半句，原文里有 `React #31`：其中 ` #` 被 YAML 当成注释起始符，**`#31` 之后的内容全部丢失**（同一机制对记忆文件的 frontmatter 一样成立 —— 都是 YAML）。技能没有消失、解析没有报错，所以此前所有"看一眼 frontmatter、觉得没问题"的检查都放过了它。

**教训**：

- 「解析成功」不等于「字段完整」—— `#` 类截断只有断言（§4.1）看得见，`check-skill.js` 也拦不住。
- 这类残缺**只损失触发面、不损失功能**，所以永远不会有人报告它坏了；只能在发布与复核时主动查。
- 同一个坑半年内踩两次（09-10 冒号、09-17 井号）说明：改 frontmatter 的收尾动作必须是**跑命令**，不是"再看一眼"。

## 七、怎么写：流程

### 7.1 先问清需求

- 这个技能覆盖**什么任务/领域**？
- 要处理**哪些具体场景**？边界在哪（哪些情况**不**该触发）？
- 需不需要可执行脚本，还是纯说明就够？
- 有没有**现成参考资料**要打包进去？

需求稀疏时先问，别猜着写 —— 猜出来的技能会写得太宽（什么都想覆盖）或太窄（只覆盖你想到的那一个例子）。

### 7.2 定触发面（description）

description 进模型视野，正文不进。它的任务只有一个：**让模型在正确的时刻想起这个技能**。

系统提示里技能容易**触发不足**（该用时不用），所以 description 要**稍微推一把**：

- 第一句说清"这个技能能干什么"。
- 之后堆**具体触发线索**：用户会说的原话、文件类型、路径片段、报错片段、界面线索。
- 明确包含"即使对方没说出 X 这个词"这类兜底。
- 有**近似但该走别的技能**的情况时，把边界也写进去。

好例子：

```
为 DSH 编写、修改和验证技能（SKILL.md）。…… 无论用户是要新建技能、改正文或 frontmatter、
诊断「技能装了却不出现」、还是问该写多长、该不该拆文件，都要用本技能 —— 即使对方没说出 skill 这个词。
```

坏例子：

```
帮助处理技能相关的事情。
```

坏例子里没有任何可区分的线索，模型无法把它和别的技能分开。

### 7.3 写正文

按「先结论、再依据、最后细节」组织：

1. **一段话定位** —— 这个技能解决什么问题、服务谁、在什么前提下用。
2. **判据与规范** —— 硬事实（字段、优先级、限制），标明出处。
3. **流程** —— 可直接照做的步骤，每步带判读标准。
4. **边界与反例** —— 什么时候不该用、容易踩的坑。
5. **验证** —— 怎么证明做对了。

写作要点：

- **用祈使句**，直接说要做什么。
- **解释为什么**，别只下命令。模型判断边界靠的是理解意图，不是背规则；满屏 MUST/NEVER 反而让它僵化。
- **别写时效性内容**（"当前最新版是 0.1.5" 半年后就是错的）—— 写成"怎么查当前版本"。
- **术语前后一致**，同一个东西别换三种叫法。

### 7.4 决定要不要 scripts / references

**加脚本**，当操作是确定性的（校验、格式化）、同一段代码会被反复现场重写、或需要显式错误处理。脚本省 token 也比现场生成的代码可靠 —— 而且能被执行而不必读进上下文。

**拆 `references/`**，当：

- SKILL.md 超过 500 行；
- 内容有彼此独立的领域（比如"Windows 做法"和"Linux 做法"）；
- 有很少用到的高级内容（放正文会稀释主流程）。

SKILL.md 只留**导航 + 主流程**，细节下放到 references 并从正文指过去，说明**什么时候该去读它**。大参考文件（300 行以上）开头放目录。

### 7.5 骨架模板

```markdown
---
name: kebab-case-名字
description: <做什么>。Use when <具体触发线索、原话、文件类型、报错片段>，即使对方没说出 X 这个词。
whenToUse: <可选，一句话场景>
---

# 标题

一段话定位：解决什么问题、服务谁、什么前提下用。

## 判据 / 规范
硬事实，标明出处。

## 流程
1. 步骤 —— 带判读标准
2. 步骤

## 边界与坑
什么时候不该用；已知会踩的坑。

## 验证
怎么证明做对了。

## 详见
- [references/细节.md](references/细节.md) —— 什么时候读它
```

### 7.6 把事故沉淀进正文（别只留在会话记忆里）

会话记忆会消散，技能正文不会 —— 这是技能最被低估的用途：**它是上一个自己给下一个自己留的教训**。写不写只有一条判据：

| 内容 | 处置 |
|---|---|
| 能靠读代码 / git / 配置文件推出来的 | **不写** —— 写进去只是会腐烂的冗余 |
| 踩过一次坑才知道的：机制、症状、误判路径、修法 | **写**，并写清"怎么发现的" |

四条格式要求：

1. **每条带日期**，并标 **实测** 或 **未验证**。只有真跑过、有命令输出或产物为证的才算实测；推论、文档抄来的、听来的都标未验证 —— 别让未验证的经验穿上实测的外衣。
2. **日期是出处，不是时效断言。** 「2026-09-17 实测」不会过期；「当前最新版是 0.1.5」半年后就错了（§7.3）。这两件事不矛盾，别拿一条否定另一条。
3. **症状 → 嫌疑层 的速查表比长篇叙述好用。** 复盘写得再细，真出事时人只会问"现在先查哪"。本技能域内的速查表：

   | 症状 | 先查哪里 |
   |---|---|
   | 技能从目录里消失 | frontmatter 能否解析（`: `，§2.7）→ 跑 `check-skill.js` |
   | 技能在，但从不触发 | description 是否被 `#` 截断（§2.7）→ 触发线索是否太泛（§7.2） |
   | 正文改了没生效 | 是不是改到了发布副本而不是私有原件（§九） |
   | 公开产物里有本机路径 / 人名 | 同步前漏跑禁用词扫描（§九） |
   | 发布版行为和本机不一样 | 打包清单是否多带了文件（§九） |

4. **长复盘下放 `references/case-YYYYMMDD.md`。** SKILL.md 里只留一两行指针 + 最关键结论（§六 就是这么处理的：三起事故各留结论）。什么时候拆，判据同 §7.4 —— 内容长到会稀释主流程才拆，别为归档而拆。

沉淀的时机是**事故当场**，不是"回头补"。回头补的代价是重演一遍排查。

## 八、篇幅与拆分

| 体量 | 处置 |
|---|---|
| < 100 行 | 可能太薄，先想清楚有没有漏掉边界情况 |
| 300–500 行 | **目标区间**（一条实践约定，2026-09-10 定） |
| > 500 行 | 拆 `references/`，正文留导航与主流程 |

**不要为了数字硬拆。** 拆分的判据是"内容有没有独立领域"，不是行数本身 —— 把一个连贯的流程砍成两半扔进两个文件，比长一点更糟。`references/` 下的文件不计入正文篇幅，可以放开写。

## 九、发布：私有原件与发布副本

我们的技能有**两份**，职责不能混（2026-09-13 定的规矩）：

| | 路径 | 用途 |
|---|---|---|
| **私有原件** | `$DSH_HOME/skills/<name>/` | 日常使用与修改的**唯一**场所（技能扫描根，rank 400，§2.4） |
| **发布副本** | `<workspace>/publish/` | 脱敏后发到 GitHub / npm 的那一份，是**产物**不是工作区 |

### 9.1 两条硬规矩

1. **平时只改私有原件；要发布时再生成脱敏副本。** 发布副本不在任何技能扫描根里（2026-09-17 核本机 `--dump-config` 里没有 `customSkillDirs`，查法见 §1.1），所以改它既不影响本机行为、也不会自动上线 —— 在它上面改东西是最容易白干的一种错。
2. **同步副本进公开发布物之前，必须跑一遍禁用词扫描。** 这条是拿真事故换来的，见 9.2。

### 9.2 事故：公开产物的 0.1.1 / 0.1.2 里带着内部信息（2026-09-13 实测）

复核发布产物时发现，某个技能已发布的 0.1.1 / 0.1.2 里带着这些内容：

- 本机绝对路径：插件源码目录、profile 的 `package.json` 路径
- 真人名
- 内部称呼

它们在**私有原件里完全正常** —— 本来就是自己用的东西 —— 但公开出去不合适。**具体字符串不写进这里**：本技能正文自己也会被发布，把泄漏内容抄进来等于二次泄漏。词表放在发布树之外的词表文件里。

**扫描做法**：

```powershell
# 词表放发布树之外（如 $DSH_HOME\publish-scan-words.txt，按需自建、一行一个词）；
# 词表放进发布树等于它自己先泄漏
$words = Get-Content "$env:DSH_HOME\publish-scan-words.txt"
Get-ChildItem -Path <发布副本目录> -Recurse -File |
  Where-Object { $_.Extension -in '.md','.yml','.yaml','.json','.js','.ts' } |
  Select-String -Pattern $words
```

管道机制 2026-09-17 在本机 PowerShell 上实测可用（只读扫目录）；**按发布物类型补词表**才是真正花时间的部分。

**命中不等于必须删。** 判断标准是"公开后有没有危害"，不是"命中了没有"：说明性的示例路径可以留（本技能正文自己就有 `$DSH_HOME\...` 这类路径，写成真实盘符时扫描才会命中），机密的、能定位到人的、能暴露内部结构的必须改写或删掉。逐条人工过，别阈值化。

扫完再用 `npm pack --dry-run` 核一遍打包清单（9.3）。

### 9.3 发布形制：携带技能的插件

技能自己不是 npm 包。我们的发法是「**携带技能的插件**」：`cordis.patch.yml` + `skills/`，**不带 lib 代码**。已有三个技能是这样发出去的：`dsh-repair`、`dsh-skill-authoring`、`dsh-subagent-delegation`。

打包内容要过两道闸：

1. `package.json` 的 `files` 白名单 —— 只列扩展自有文件（`cordis.patch.yml`、`skills/`、`README`、`LICENSE`）。
2. `npm pack --dry-run` 核对**真实**打包清单 —— 别信 `files` 写了什么，信 `npm` 输出什么。多出一个文件就多一份泄漏面。

原则一句话：**只带扩展自有文件**，别的私人定制（其它技能、profile 配置、memory）一律不进去。

## 十、交付前自检清单

- [ ] `check-skill.js` 退出码 0（frontmatter / 引用 / 锚点 / 篇幅全过）
- [ ] frontmatter 跑过**完整性断言**（§4.1），而不只是"解析没报错"
- [ ] `name` 与目录名一致，且没打算再改
- [ ] description 有具体触发线索，且**不含 `: `**
- [ ] 正文用祈使句，关键处解释了为什么
- [ ] 没有时效性断言（「当前最新版是 0.1.5」这类；经验条目的**出处日期不算**，见 §7.6）
- [ ] 术语前后一致
- [ ] 超过 500 行已拆 references，且正文里有指向它们的入口
- [ ] 改了 description 或判定逻辑 → 跑过 A/B 对照，且知道差距在哪
- [ ] 整个技能目录已备份（尤其动过 frontmatter 之后）
- [ ] 有真实例子（具体到路径、命令、判读标准），不是抽象描述
- [ ] 只改了私有原件；发布副本是按 §九 的流程重新生成的，不是在副本上直接改的
- [ ] 要发布 → 已跑禁用词扫描、命中项逐条判断过，`npm pack --dry-run` 核对过打包清单（§九）
- [ ] 新踩的坑当天写进正文（§7.6），带日期与「实测 / 未验证」

## 十一、相关

- 官方规范原文 → `<DSH 安装树>/node_modules/@deepseek-ai/dsh-skill-filesystem/README.zh.md`
- DSH 起不来 / 技能加载失败 / 链接损坏 → `dsh-repair` 技能
- 写 DSH 插件（宿主插件、界面插件）→ `dsh-plugin-development` 技能
- 本技能的静态校验工具 → [`scripts/check-skill.js`](scripts/check-skill.js)
- **旧的重度评测工具** → 原 `skill-creator` 技能（Anthropic 出品，Python 基准脚本 + eval viewer + 盲比流程，18 个文件）。2026-09-10 与 `write-a-skill` 一起归档在 `<archive>/skill-merge-20260910/`，从技能目录移除是为了消掉三者的触发面冲突。**需要跑量化基准或盲比时再去那里取**；日常按 §五 做 A/B 对照就够。

