前言¶
DSH 里跑过一次成功的任务之后,经验往往只留在会话里。下次遇到同质任务,模型还是从零摸索,上次踩过的坑可能再踩一遍。已有的做法要么靠人工写 README,要么靠人记住教训,都没法在下次执行前自动浮出来。
yangyiqun747/dsh-plugin-playbook 是 DSH 的「经验复用 + 交付闸门」插件,维护者是 yangyiqun747,分类为工作流。思路是:一次任务成功后,把「可复用的 SOP + 踩过的坑」沉淀成一条 playbook;下次遇到同质任务时,它作为原生 Skill 出现在技能目录里,模型按需加载并照着做。同一个任务族累计到足够样本后,SOP 可以升级成交付闸门:执行前必须让用户 review,交付前必须逐项拿到客观证据,否则写文件的动作会被硬拦截。
下面介绍这个插件的实际做法。
核心功能¶
插件一共提供了三组能力。
经验库工具:5 个¶
1、playbook_save:保存一条经验。
2、playbook_search:按相关性检索。
3、playbook_get:取全文。
4、playbook_promote:把条目转正为 active。
5、playbook_feedback:回写本次使用结果(ok 或 fail)。
闸门工具:6 个¶
1、gate_status:看本会话与工作区里有哪些闸门、历史通过率。
2、gate_propose:提议一条闸门(写入时是「未确认」,不拦截任何动作)。
3、gate_confirm:通过原生提问通道询问用户,用户同意后才落库。
4、gate_start:先通过原生提问通道把本次方案交给用户 review,用户点「开始执行」后才启用闸门。
5、gate_check ×N:每项记录客观证据(命令 + 退出码 + 输出摘要)。
6、gate_finish:全部必过项就绪后放行交付,并写回统计。
外加一个硬拦截守卫(在 tools/pre-execute 上拦住 write / edit / present,直到已确认的 L2+ 闸门逐项通过)、一个 Skill Provider(active 状态的每条 playbook 以 playbook-<id> 出现在技能目录,用内置 skill 工具加载)、一条斜杠命令 /playbook,以及两段系统提示(playbook:usage 经验库用法、playbook:gates 当前闸门状态播报)。
存储:纯 Markdown,可 git 可手改¶
数据落在工作区内:
<workspace>/.dsh/playbooks/<id>.md # 经验
<workspace>/.dsh/gates/<id>.md # 闸门
frontmatter 里带 id、title、status(draft / active / deprecated)、scope、tags、whenToUse,以及 stats(uses、ok、fail、lastUsed、lastOutcome)。正文按「何时使用 / 前置条件 / SOP / 坑 / 验证 / 证据」分段。
文件名 <id> 会被规整成 ASCII kebab-case。原因很实际:active 条目要变成原生 Skill,而 skill 名(playbook-<id>)必须是 ASCII。规则是抽掉标题里的 ASCII 字母数字拼成 kebab(「为 DSH 开发…Host 插件」→ dsh-host);标题里完全没有 ASCII 时退回 pb-<8位内容哈希>。中文标题本身不受影响,完整保留在 frontmatter 的 title 字段里。
召回方式¶
1、Skill 目录:active 条目以 playbook-<id> 出现,description 用 whenToUse,模型自行判断相关性后加载。
2、主动检索:playbook_search 按 tags(权重 6/4)加关键词(标题 5、标签 4、何时使用 3、正文 1)打分,并按 stats.ok/fail 微调,已验证有效的排在前面。
3、全文:playbook_get。
生命周期与自动降级¶
playbook_save -> draft 只有用户确认后才转正
playbook_promote -> active active 才会作为 Skill 暴露、才会被召回
↓ 复用
playbook_feedback(ok|fail) 写回 stats
↓ 连续失败
自动降级 -> draft / deprecated
自动降级只在 active 上触发,规则如下:
fail >= 2且ok === 0→deprecated(从来没成功过,直接淘汰)。fail >= 3且fail > ok * 2→deprecated(成功过但基本不灵)。fail >= 2且fail > ok→ 退回draft(需要修订)。
原文特别指出顺序不能反:draft 分支必须排在最后,否则条目在第 2 次失败时就离开 active,后面那些 active 专属的 deprecated 判断会变成永远够不到的死代码。
交付闸门:先 review,再放行¶
经验库解决「怎么做」,闸门解决「做完敢不敢交」。闸门的定义只能由用户确认,插件只能提议。
风险分把一个任务族量化成 R,再由 R 决定门有多硬。简化地说,D 由改动面、链路长度、认知密度等因子算出(有客观验证手段会打折,不可逆动作会加分),P 由历史通过率与用户返工次数算出,两者按 R = 0.5 × D + 0.5 × (1 − P) 合成。用户返工(reworks)在 P 里的权重是普通成功/失败的 2 倍。
R |
等级 | 行为 |
|---|---|---|
| < 0.25 | L0 |
不设闸门 |
| 0.25 – 0.5 | L1 |
逐条自检并列证据(软提醒,不拦截) |
| 0.5 – 0.75 | L2 |
客观验证,write / edit / present 被硬拦截 |
| ≥ 0.75 | L3 |
同 L2,另要求独立验证者:至少一个必过项由别的 agent 自己调 gate_check 记录 |
一套完整流程是:
1. gate_status 看本会话与工作区里有哪些闸门、历史通过率
2. gate_propose 提议一条闸门(未确认,不拦截)
3. gate_confirm 通过原生提问通道直接问用户;同意后才落库
4. gate_start 先通过原生提问通道把方案交给用户 review;
用户点「开始执行」后才启用闸门
5. gate_check ×N 每项记录客观证据(命令 + 退出码 + 输出摘要)
6. gate_finish(pass) 全部必过项就绪 -> 放行交付,写回统计
(L3 时另要求第 5 步里至少一项由别的 agent 记录)
不想经过模型时可以直接看:/playbook gates 列出工作区里的闸门(等级、是否已被用户确认、通过率、按当前数据建议的等级),/playbook gates <id> 看单个闸门的检查项与历史。
四条不变量¶
1、不许自证放行:gate_confirm 与 gate_start 都通过 ctx.userQuestions.ask 直接问用户,答案由人在界面上给出。模型只能在原生通道不可用时用 user_confirmed 兜底,且兜底会记进 history / 工具输出。
2、L2 以上必须有客观证据:gate_check 要求命令 + 退出码 + 输出摘要,自评不算证据;L3 还要求至少一条证据的记录人不是开启闸门的那个 agent。
3、闸门定义只能由用户确认后变更:gate_propose 写出的永远是 confirmed_by_user: false,连等级被改动都要重新确认。
4、必须有熔断与逃生舱:同一个闸门连拦 2 次(MAX_BOUNCES)后自动打开熔断、放行并把判断权交回用户;用户说「这次不用闸门」时用 gate_finish(exempt) 出闸,豁免不计入统计。
闸门状态按工作区存放,不按 agent¶
gate_start 把会话建在工作区的闸门目录上,所以同一个工作区里的所有 agent共用一条闸门。用原生 subagent 派出去的子 agent 落地在同一个会话,它自己调 gate_check 记的证据会被标记 verifier: <子 agent id> 并计入 independent;子 agent 的 write / edit / present 一样会被硬拦截;gate_finish 只有开启闸门的那个 agent 能调。
这是 L3「独立验证者」的实现方式:不是让模型声明「我找了人复核」,而是让另一个 agent 自己调用工具、由宿主填上它的身份。模型无法伪造。
失败时的降级与既有机制的关系¶
守卫自己出错时不会静默放行:它会把错误写进闸门状态段落、警告用户,然后按「未通过但放行 + 警告」处理。
插件不造轮子:执行前 review 用原生 ctx.userQuestions.ask,动作级阻断用原生 tools/pre-execute,闸门状态播报用原生 ctx.systemPrompt.section,插件不 import 任何 @deepseek-ai/*。plan mode 只是尽力而为——首次真实运行里 ctx.get('planMode') 在插件上下文返回空,所以 gate_start 不再依赖它,用户 review 走提问通道,plan mode 能拿到就顺带切,拿不到就把原因写进 plan_mode 字段。任务已经跑在 AgentTeams 团队里时不叠门禁,用它的 requirements/review verdict,闸门只负责把 verdict 回写成 gate_check 的证据。
README 里附了一组真实宿主里的实测记录:tools/pre-execute 硬拦截生效(闸门激活时 write 被拒,错误原文含缺证据清单,探针文件未被创建);ctx.userQuestions.ask 确认闸门生效;ctx.get('planMode') 在插件上下文取不到;gate_propose 的 factors 落盘曾有 bug(已修);提示段落对 failed 项的播报曾有 bug(已修);重复 install_bundle 会返回 application: failed。每条都对应了回归测试或具体输出原文。
安装与启用¶
dsh plugin --profile desktop add <本目录的绝对路径>
卸载:
dsh plugin --profile desktop remove dsh-plugin-playbook
从本地目录路径安装,不从 GitHub 拉取。安装包是 ESM,main 为 lib/index.js,并声明了 cordis.patch.yml 补丁文件;Node 版本要求 >=22。
启用后配置写在 cordis.patch.yml 的 config:
- insert:
- id: playbook
name: dsh-plugin-playbook
config:
dir: .dsh/playbooks # 经验库,相对工作区
gateDir: .dsh/gates # 闸门库,相对工作区
promptSectionOrder: 140 # 系统提示段落排序
slashCommand: true
安装期如果 install_bundle 报的错跟本插件无关(例如 ENOENT ... dsh-plugin-whale-maid-1.0.0.tgz),那是 profile 的 pnpm-lock.yaml 里某条 file: 依赖指向了已删除的本地压缩包,pnpm 每次 install 都会去读它。修法是在对应源目录执行 pnpm pack --pack-destination <lockfile 期望的目录>,再用 SHA512 重算并更新 lockfile 里该条目的 integrity。
测试:
npm test
# 等价于 node --test "tests/*.test.mjs"
注意别写成 node --test tests/,Node 会把它当模块路径而报 MODULE_NOT_FOUND。
典型用法¶
完整走一遍的流程如下。
1、任务成功后沉淀经验:调 playbook_save 写入 SOP 与「坑」段落。
---
id: "windows-sandbox-build"
title: "Windows 沙箱里跑构建"
status: "active"
scope: "project"
tags: ["windows", "sandbox", "build"]
whenToUse: "需要在沙箱内执行 pnpm/node 构建时"
stats:
uses: 3
ok: 2
fail: 1
---
# Windows 沙箱里跑构建
## 何时使用
## 前置条件
## SOP
## 坑
## 验证
## 证据
2、确认转正:用 playbook_promote 升到 active,之后它以 playbook-windows-sandbox-build 出现在技能目录。
3、下次同类任务先检索:playbook_search 按 tags 与关键词打分召回,或直接 playbook_get 取全文。
4、任务族样本够了,提议闸门:gate_propose 给出检查项与等级建议,此时不拦截。gate_confirm 走原生提问通道请用户确认。
5、执行前 review 并开闸:gate_start 把方案交给用户 review,用户点「开始执行」后闸门生效。
6、逐项取证:每做完一项检查,调 gate_check 记录命令、退出码、输出摘要。
7、交付判定:全部必过项就绪后调 gate_finish(pass) 放行并写回统计;否则只能 gate_finish(fail)。failedEvidence 只统计 required 项,optional 项失败不阻塞 pass。
适用场景与注意¶
适合用在:同一类任务反复出现、上次的成功做法值得固化的场合,尤其是出现频率高、改动面大、或者「做完不敢直接交」的任务族。对个人练手、一次性脚本,L0 不设闸门,插件的经验库也只有在愿意写 SOP 时才有收益。
注意几点:
- 插件以当前 dsh 进程的权限运行,装的代码会在你的工作区读写文件,安装前应检查源码与许可证(
MIT)。 - 星标与下载量在目录页上并不高,属于社区里的个人维护项目,长期维护需要自行判断。
- 闸门行为依赖原生
tools/pre-execute与ctx.userQuestions.ask可用;庇护通道不可用时的兜底会被记录,且默认走「未通过但放行 + 警告」而不是静默放行。 - 存储是工作区内的纯 Markdown,可以直接 git 管理,但也意味着没有额外的权限隔离或加密。
结语¶
一句话概括这个插件的价值:成功经验 → 结构化 playbook → 同质任务自动召回 → 用户确认成闸门 → 交付前强制达标。它解决的不是模型能力问题,而是经验留不下来、交付缺客观证据这两件事。
目录页:https://www.skillhub.cn/plugins/yangyiqun747/dsh-plugin-playbook
GitHub:https://github.com/yangyiqun747/dsh-plugin-playbook