前言¶
用智能体写功能时,常见情况是:一句话需求丢进对话,模型直接改代码。规格只活在聊天记录里,下一轮上下文一挤,当时答应过的边界、验收条件和不改动的范围就对不上了。人要回头核对「到底做成了什么」,只能翻轨迹、对 diff,没有一份可以过门的书面约定。
规格驱动开发(Spec-driven development)把这件事反过来:先把「为什么改、改什么、怎么算做完」写成仓库里的 Markdown,人批准之后再实现,实现完再对照场景逐条验收。OpenSpec 把这一套落成 openspec/ 目录:进行中的变更放在 changes/,归档后合并进 specs/。DeepSeek Harness(dsh)本身是「一切皆插件」的运行时,模型、工具、会话、UI 都可以装卸;社区维护者 tianji-qingtian 做的 dsh-spec-loop,就是把这套闭环接到 Harness 的 /spec 命令上。
本文按插件目录页、GitHub 仓库 README / package.json / 发布标签交叉核对后整理:它是什么、命令怎么走、如何安装,以及使用时要注意的边界。DeepSeek Harness 仍处于 developer preview,插件 API 可能出现不兼容变更;文中版本以仓库当前发布的 v0.1.2 为准。
这是什么¶
dsh-spec-loop 是一款面向 DeepSeek Harness 的开发与运行时插件,由 tianji-qingtian 维护,许可证为 MIT。目录页与 GitHub 仓库均显示 5 星(以打开页面时的数字为准)。主要语言是 JavaScript,package.json 里的版本号是 0.1.2,与 GitHub Release / tag v0.1.2 一致。
它解决的问题可以写成一句话:用 /spec 命令族驱动「生成规格 → 批准 → 按任务实现 → 对照规格逐条验收 → 归档」,变更目录与 OpenSpec 的布局兼容,落在工作区的 openspec/ 下。
需要分清两件事:
- 它采用 OpenSpec 的目录格式和阶段划分,校验规则按 OpenSpec CLI 的核心条目自实现;不依赖单独安装 OpenSpec CLI。
- 它是社区插件,收录在独立站点 DeepSeek Harness 插件库。该目录自称与 DeepSeek / 幻方无官方从属关系,不是官方应用商店。
package.json 的 dsh.client.platform 声明为 web:浏览器半边挂在 Web UI 上,输入框上方会多一张规格变更卡。仓库 README 也按 web profile 来写安装步骤。
核心功能¶
/spec 命令族¶
插件注册一个 /spec 命令,再按子命令路由。命令 handler 只做流程编排和文件系统操作;提案正文、任务清单、规格增量和实现代码,都交给当前会话的 agent 主模型,通过 agent.steer 注入任务、使用完整工具集生成。
README 列出的子命令如下:
| 子命令 | 作用 |
|---|---|
init |
创建 openspec/project.md 和目录结构 |
new <目标> |
澄清后生成提案 / 任务 / 规格增量,并自动校验 |
status |
只读:当前 change-id、阶段、任务进度 x/y |
list |
列出活跃变更和能力规格 |
show <id> |
查看提案全文(有 design.md 时一并展示) |
approve <id> |
批准,打开实现门 |
implement <id> |
按 tasks.md 逐项实现并勾选 |
verify <id> [--deep] |
按 Scenario 验收;--deep 改用主模型 |
archive <id> |
合并增量到 specs/,目录移入归档 |
validate [id] |
OpenSpec 格式校验(new 之后会自动跑) |
edit <id> |
修订提案,状态回到 proposed |
/spec new 最多提 3 个内置选择题,分别覆盖范围、约束、验收方式,语言跟随目标描述,走 Harness 的问答 UI。子代理会话或缺少 UI provider 时,会跳过澄清,直接往下生成。
OpenSpec 兼容目录¶
初始化之后,工作区里是这样一套布局(与 OpenSpec 的 openspec/ 形状对齐):
<工作区>/openspec/
├── project.md
├── specs/<能力>/spec.md
└── changes/
├── <change-id>/
│ ├── proposal.md
│ ├── tasks.md
│ ├── design.md # 可选
│ ├── verify.md # 验收后由插件写出
│ └── specs/<能力>/spec.md
└── archive/YYYY-MM-DD-<change-id>/
规格增量用 ## ADDED|MODIFIED|REMOVED Requirements 分段,每条 Requirement 至少要有一个 #### Scenario:。这是 OpenSpec 的校验规则,插件内置了同款检查:提案生成后自动跑;失败会把修正请求再 steer 回 agent(有重试上限)。approve 会拒绝未通过校验的变更,archive 会拒绝目录里不存在的变更。
归档时按 Requirement 逐条合并进 specs/<能力>/spec.md:ADDED 追加,MODIFIED 按名称替换(没有同名则追加),REMOVED 删掉对应块,然后用一次 mv 把变更目录挪到 changes/archive/。
批准门和持久状态机¶
状态按这条链走:
proposed → approved → implemented → verified → archived
任意阶段都可以 /spec edit 回到 proposed,改完需要重新批准。implement 拒绝状态还不是 approved(或实现链更后面阶段)的变更。门禁读的是面板渲染用的同一份会话投影,显示态和行为态共用一份数据。
状态不是另写一套自定义会话事件。外置插件不能安全往 SessionEventMap 里加新类型(持久化读路径会拒绝未知的非 ignorable 事件),所以转移只折叠标准事件:command/run / command/done 成功对,再加上 agent 回复里的机器标记(如 SPEC_CHANGE_ID:、SPEC_IMPLEMENTED)。重启之后变更卡、阶段和门禁还在;把插件卸掉,会话日志也仍然可读。
有一条使用上的限制:批准状态按会话折叠。在一个会话里 approve,不会自动对另一个会话生效。
逐条验收和输入框上方的变更卡¶
/spec verify 会按每条 Requirement 的每个 Scenario 做一次受限裁判调用:默认用 flash、关掉 thinking;加 --deep 则换成主模型。proposal.md 里用 bash 代码块声明的验证命令会先经 ctx.shell 执行,输出再进入裁判提示。结果写入 verify.md,带 ✅/❌ 表格和原始判定文本。
Web UI 里,输入框上方的 dock 会显示一张全宽变更卡(README 写成 📐 Spec):当前 change-id、阶段、任务进度 x/y,以及下一步该跑的命令。进度来自 Harness 自带的 todos 投影——实现阶段的提示词会让 agent 把 tasks.md 镜像进 todo_write,面板不额外打 RPC。文案走 locale 服务,支持中英。
安装与启用¶
插件以当前 dsh 进程的权限运行,安装时可能执行代码。装之前应检查源代码仓库和许可证;需要可复现安装时,应固定 commit 哈希或 release tag。
目录页给出的安装命令是:
dsh plugin add github:tianji-qingtian/dsh-spec-loop
仓库 README 的前置条件:dsh CLI 必须在 PATH 上。如果平时只用 npx 启动 Harness,本机没有全局 dsh,会报 command not found。可以先全局安装:
npm install -g @deepseek-ai/dsh
pnpm add -g @deepseek-ai/dsh 也可以,前提是 pnpm 的全局 bin 目录已在 PATH 里;或者不装全局,给后续命令加上 npx @deepseek-ai/dsh 前缀。
README 建议把 bundle 加进 web profile,并优先钉死 release tag(文档写的是 #v0.1.2;#main 会跟最新提交)。lib/ 产物已经提交在仓库里,安装时不跑构建:
dsh plugin --profile web add "github:tianji-qingtian/dsh-spec-loop#v0.1.2"
dsh --profile web
add 只改 profile 文件,正在跑的实例不会热加载,需要用对应 profile 重启。重启后输入框上方应出现规格变更卡,host 端加载完成后 /spec 才会注册。可在 Settings → Plugins 里确认列表中有 dsh-spec-loop。
目录页补充了固定 commit 的写法,形式为:
dsh plugin add github:tianji-qingtian/dsh-spec-loop#commit
把 commit 换成实际哈希即可。当前 tag v0.1.2 对应的 commit 是 0783a43190d43accb93238f85d06d231e373bd81(以 GitHub tags API 为准)。
package.json 声明的 Node 引擎是 ^22.19.0 || >=24.0.0,peer 依赖指向 @deepseek-ai/dsh-* 的 ^0.1.0-rc.6 以及 @deepseek-ai/cordis ^4.0.1。Harness 还在快速迭代,装之前应对一下本机 dsh 版本是否匹配。
典型用法¶
下面命令来自仓库 README 的示例,change-id 以 add-user-login 为例(/spec new 生成提案后,以 agent 回报和 /spec list 里的实际 id 为准)。
先初始化目录:
/spec init
用一句话目标开一个变更。插件会先澄清,再让 agent 写 proposal.md、tasks.md 和规格增量,然后自动校验:
/spec new 用户登录功能
查看当前卡片、列出活跃变更、打开提案:
/spec status
/spec list
/spec show add-user-login
人审阅通过后再批准。没批准之前,implement 会被拒绝:
/spec approve add-user-login
/spec implement add-user-login
实现完成后对照 Scenario 验收。默认 flash;需要主模型时加 --deep:
/spec verify add-user-login
/spec verify add-user-login --deep
验收通过再归档,增量合并进 specs/,目录进入 changes/archive/:
/spec archive add-user-login
中途要改提案:
/spec edit add-user-login
状态会回到 proposed,需要重新 approve 才能再实现。输入框上方的变更卡会同步 change-id、阶段、x/y 进度和下一步命令;只想看、不想改状态时用 /spec status。
适用场景与注意事项¶
比较适合这些情况:
- 在 DeepSeek Harness 的 Web UI 里做功能开发,希望规格、任务、实现、验收留在仓库文件里,而不是只存在于一轮对话。
- 已经或准备采用 OpenSpec 的
openspec/布局,希望 Harness 侧的变更目录可以直接被 OpenSpec 那套工具识别。 - 需要「不批准不实现」的门禁,以及按 Scenario 产出
verify.md的书面验收。
使用前值得记住这些边界(均来自仓库 README / 需求文档,不是额外推断):
- 权限与安全。插件以当前
dsh进程权限运行;verify还会执行proposal.md里声明的 bash 验证命令。安装前应阅读源码和 MIT 许可证,不要对不信任的仓库执行dsh plugin add。 - 平台。客户端声明为 web,变更卡挂在 Web UI 的 composer dock。README 的安装路径也是
--profile web。 - 会话维度的批准。A 会话里批准过的变更,B 会话不会自动视为已批准。
- 不监听写文件来强制门禁。v1 只做命令级门:未
approve时拒绝/spec implement,并不会拦截 agent 用普通工具直接改实现文件。 - 不兼容 GitHub spec-kit 目录格式。需求文档写明 v1 只兼容 OpenSpec;spec-kit 留作后续扩展。
- Harness 预览版。官方说明 DeepSeek Harness 仍在 developer preview,核心插件和 API 会继续变。README 也提醒可能出现破坏性变更。
- 同名项目不要装错。社区里还有
dsh-specflow、ds-spec-loop等规格相关项目,机制和安装源都不同。本文只对应github:tianji-qingtian/dsh-spec-loop。
小结¶
dsh-spec-loop 把规格驱动开发接到 DeepSeek Harness 上:/spec 负责开门和落盘,agent 负责写提案和改代码,OpenSpec 形状的 openspec/ 作为可审查的事实来源。批准门、格式校验、逐 Scenario 验收和输入框上的变更卡,都是为了让「先约定、再实现、再对照」在一次会话里跑得完。
目录页:https://deepseek-harness-plugin.com/zh-CN/plugins/dsh-spec-loop/
GitHub:https://github.com/tianji-qingtian/dsh-spec-loop